title: Django 2FA works locally but fails (silently) on server
body: <h1>The Problem</h1>
  <p>I need to implement two-factor authentication for a Django project. I am using <a href="https://django-two-factor-auth.readthedocs.io/en/stable/configuration.html" rel="nofollow noreferrer">Django Two-Factor Authentication</a> which works just fine locally both with Google Authenticator and our SMS gateway. The issue occurs when I publish the app to the test server. The login works as normal but when I fill in the token it will simply redirect me back to the initial login step to fill in my credentials again. It does not give me any error messages in the UI and, as far as I can see, none in the logs either.</p>
  <p>Don't know if it's relevant, but the app is running as a Docker Swarm service on the server.</p>
  <h1>What I have tried</h1>
  <p>Due to the lack of feedback and knowledge of the 2FA library as well as the OTP-library I don't really know where to start. I'm pretty sure the settings are as good as identical between my local machine and the test environment. The package versions are the same. I even made sure the time and time zones are identical between my machine and the server.</p>
  <p>Looking in the database in the tables for the OTP library the failure count is 0 and <code>last_t</code> is incrementing every time I try to log in. This tells me that the token itself is verified, as per the Django-OTP documentation:</p>
  <blockquote>
  <p>BigIntegerField: The time step of the last verified token.  To avoid
  verifying the same token twice, this will be updated on each
  successful verification.  Only tokens at a higher time step will be
  verified subsequently. (Default: -1)</p>
  </blockquote>
  <hr />
  <p>Any suggestions are much appreciated. I know I haven't provided much concrete details of my exact implementation, but I am hoping that someone might have some general idea of what the problem might be. Anyway let me know if you need something more concrete.</p>
  <p>Thanks,</p>
  <p>niknoe</p>
  <h1>Edit 1</h1>
  <p>I was wrong, there was actually something in the logs I didn't see before:</p>
  <pre><code>Requested step 'token' is no longer valid, returning to last valid step in the wizard.
  </code></pre>
  <p>So maybe this can indicate that I have some drift causing token to be invalid?</p>
  <p>Versions are</p>
  <ul>
  <li>Django 2.2.20</li>
  <li>django-otp 1.0.3</li>
  <li>django-two-factor-auth 1.13.1</li>
  </ul>
  <p>I'll try to include the relevant code</p>
  <p>My settings.py is divided into environment settings that each settings.base.py. All the relevant code for 2FA is in settings.base.py:</p>
  <pre class="lang-py prettyprint-override"><code>ISTALLED_APPS = [
      ...
      'django_otp',
      'django_otp.plugins.otp_static',
      'django_otp.plugins.otp_totp',
      'two_factor'
  ]
  
  MIDDLEWARE = [
      ...
      'django.contrib.auth.middleware.AuthenticationMiddleware',
      'django_otp.middleware.OTPMiddleware',
      ...
  ]
  
  LOGIN_URL = 'two_factor:login'
  
  # Not sure if these are relevant
  TIME_ZONE = 'Europe/Oslo'
  
  USE_I18N = True
  
  USE_L10N = True
  
  USE_TZ = True
  </code></pre>
  <p>This is basically all I have added in order to make it work locally on my machine.</p>