Skip to content
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

state.token_backend does not respect updated Django settings at test time #58

Open
jamescooke opened this issue Jan 3, 2019 · 1 comment

Comments

@jamescooke
Copy link

While writing a small integration test to assert that data can be retrieved from a JWT created by this lib, I found that pytest-django's settings fixture is not causing an update to state.token_backend instance (https://github.com/davesque/django-rest-framework-simplejwt/blob/128582df8f07b5e0fb74c51a0dc90d11302bba07/rest_framework_simplejwt/state.py#L9-L10).

Given a settings file with SECRET_KEY = '__SECRET_KEY__':

def test_default_is_secret(settings):
    result = settings.SECRET_KEY

    assert result == '__SECRET_KEY__'

Then when the SIMPLE_JWT.SIGNING_KEY value is updated, this test passes:

def test_settings_not_updated(api_client, url, user, settings):
    """
    When settings are updated using pytest's settings fixture, the
    ``state.token_backend`` instance has already been created with the old
    value of the setting and is not updated.
    """
    settings.SIMPLE_JWT = {
        'SIGNING_KEY': '__SIGNING_KEY__',
    }
    data = {
        'username': 'a_user',
        'password': '__PASSWORD__',
    }

    result = api_client.post(url, data=data)

    assert result.status_code == 200
    assert sorted(result.data) == ['access', 'refresh']
    jwt.decode(result.data['access'], key='__SECRET_KEY__', algorithms=['HS256'])

This test should fail because the call to jwt.decode is using key='__SECRET_KEY__', which is the "old" value - it should be key='__SIGNING_KEY__' as per the updated setting.

As per encode/django-rest-framework#2466, there is now the reload_api_settings() fn in DRF and that is used in this lib too. I have hooked into it and checked that it is definitely being called when the settings fixture is changing the settings. However, it appears to me that it's too late to update token_backend which is created at load time.

My experience here is probably just an edge case, but if a fix is on the cards, then my suggestion would be to change token_backend from being statically created to using some kind of function like get_token_backend() to generate the TokenBackend instance when required rather when loaded.

@rvdrijst
Copy link

rvdrijst commented Dec 6, 2019

I ran into the same issue. I've worked around it for my tests with a bit of monkey patching. Not ideal, but it works and it's only in the test:

import rest_framework_simplejwt.state
from rest_framework_simplejwt.state import token_backend
from django.test import TestCase

class MyTestCase(TestCase)
    def setUp(self):
        # keep a reference to the current backend
        self._token_backend = token_backend
        rest_framework_simplejwt.state.token_backend = TokenBackend('ANY ALGORITHM,
                                                                    'ANY SIGNING KEY', 
                                                                    'ANY VERIFYING KEY')
    def tearDown(self):
        # restore the original backend
        rest_framework_simplejwt.state.token_backend = self._token_backend

You could also set the testing TokenBackend in each test method instead of globally in setUp().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants