-
Notifications
You must be signed in to change notification settings - Fork 13
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
Rotate tokens every login #442
Conversation
Errh, I did not try logging into an existing mreg installation after this change, and just blindly trusted the tests. Logging in with a user that already has a token causes a crash:
Demoted to draft status until I find a solution. |
Possibly because it already contained a token from created by The tests don't have stale data in them, so that's why it didn't catch it. Could easily be provoked by adding a |
Right, thanks for the hint. I had to override
...however the request never makes it to our view in the test and is 401'd somewhere in |
To clarify, this does work in practice:
...but I haven't been able to write a test for it. I wonder if we can take a "shotgun" approach and just clear all tokens at server startup? |
This makes sense.
A crude but efficient solution. All old tokens will be invalidated on first usage anyhow, so |
It turns out that doing database operations during initialization is unsafe and discouraged: https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready Instead I opted to add a management command to delete all tokens. It should be run before starting the server, and only needs to be done once. I also added it to the Docker image and will remove once its consumers are updated. Oh, and there is a new Admin view to inspect the new |
* mreg/api/views.py (ObtainExpiringAuthToken.post): Delete existing token when logging in. * mreg/authentication.py (ExpiringTokenAuthentication.authenticate_credentials): Extend token expiry time on usage. * mreg/api/v1/tests/tests.py (MregAPITestCase.get_token_client): Set a password for the test user. (APITokenAutheticationTestCase): Rename to ... (APITokenAuthenticationTestCase): ... this. (APITokenAuthenticationTestCase.test_token_rotation): New test.
* mreg/models.py (ExpiringToken): New class. * mreg/migrations/0012_expiringtoken.py: New migration. * mreg/authentication.py (ExpiringTokenAuthentication.__init__): Use ExpiringToken instead of Token. (ExpiringTokenAuthentication.authenticate_credentials): Use token.last_used instead of token.created. * mreg/api/v1/tests/tests.py: Adjust to use ExpiringToken instead of Token. (APITokenAuthenticationTestCase.test_force_expire): Expire based on last usage rather than creation time. (APITokenAuthenticationTestCase.test_token_usage): New test. * requirements-dev.txt: New file.
* mreg/admin.py (AuthTokenAdmin): New class.
* mreg/management/commands/delete_all_tokens.py: New file. * ci/manifest.scm (mreg-wrapper): Run it before starting the server.
Hello,
This PR ensures that API tokens are rotated every login.
Using a token within the expiry window will extend the expiry time so e.g. automated jobs can keep using the same token.