django-rest-knox
django-rest-knox copied to clipboard
Migrating from rest_framework.TokenAuthentication without logging users out
Is there a recommended way to migrate to knox from DRF's TokenAuthentication—without logging users out?
If I swap in knox instead of DRF, then all users need to re-login (since their old token isn't valid). I can't seem to get both systems working simultaneously, because knox.TokenAuthentication
raises an exception (instead of returning None) if the the token is invalid, which causes Django not to try subsequent authenticators.
Ideally, I'd like a way to try knox.TokenAuthentication, then if it fails but the token works in DRF, create a knox token for that user (then at some point in the future, completely remove DRF tokens).
I suppose if you're running say a redux store you could check the token in from the browser storage/store and see if in the DRF table. If it is remove it and send back a new token from the knox table. Then slowly phase that out until the DRF table is empty or a majority of active users have switched.
Something like this would work:
from django.db import migrations
from knox import crypto
from knox.settings import CONSTANTS
def convert_tokens(apps, schema_editor):
Token = apps.get_model("authtoken", "token")
AuthToken = apps.get_model("knox", "authtoken")
db_alias = schema_editor.connection.alias
for token in Token.objects.using(db_alias).all():
digest = crypto.hash_token(token.key)
# bypass custom manager
AuthToken.objects.using(db_alias).bulk_create(
[
AuthToken(
digest=digest,
token_key=token.key[: CONSTANTS.TOKEN_KEY_LENGTH],
user_id=token.user_id,
expiry=None, # or whatever logic you want
)
]
)
# bypass auto_now_add restriction
AuthToken.objects.using(db_alias).filter(digest=digest).update(
created=token.created
)
Token.objects.using(db_alias).all().delete()
class Migration(migrations.Migration):
dependencies = [
("knox", "0008_remove_authtoken_salt"),
]
operations = [migrations.RunPython(convert_tokens)]
(keep in mind this is for the latest unreleased version of knox where the salt has been removed from AuthToken)
Remove "rest_framework.authentication.TokenAuthentication" from your views and default authentication, but keep both "rest_framework.authtoken" and "knox" in INSTALLED_APPS until the migration has run everywhere.
@jonathan-golorry just created a PR with a "safe" version of your migration