stellar / django-polaris

An extendable Django app for building modular Stellar services
https://django-polaris.readthedocs.io
Apache License 2.0
94 stars 66 forks source link

Occasional "The token is not yet valid (iat)" in SEP-24 #666

Closed yuriescl closed 1 year ago

yuriescl commented 1 year ago

django-polaris==2.3.5

Sometimes, then the SEP-24 popup is opened, we get this error:

2BC7B0DA-8ABD-41B1-A0CA-402DF02898F0

After some debugging I was able to reproduce this locally:

payload["iat"]=1674086508.2282877 now=1674086508
[2023-01-19 00:01:48 log.py:224 ERROR] Internal Server Error: /sep24/transactions/deposit/webapp
Traceback (most recent call last):
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/sentry_sdk/integrations/django/views.py", line 68, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/django/views/decorators/clickjacking.py", line 50, in wrapped_view
    resp = view_func(*args, **kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/rest_framework/decorators.py", line 50, in handler
    return func(*args, **kwargs)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/polaris/sep24/utils.py", line 65, in wrapper
    authenticate_session_helper(request)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/polaris/sep24/utils.py", line 89, in authenticate_session_helper
    jwt_dict = jwt.decode(token, settings.SERVER_JWT_KEY, algorithms=["HS256"])
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/jwt/api_jwt.py", line 168, in decode
    decoded = self.decode_complete(
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/jwt/api_jwt.py", line 136, in decode_complete
    self._validate_claims(
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/jwt/api_jwt.py", line 195, in _validate_claims
    self._validate_iat(payload, now, leeway)
  File "/home/yuri/github/anchor/.venv/lib/python3.8/site-packages/jwt/api_jwt.py", line 221, in _validate_iat
    raise ImmatureSignatureError("The token is not yet valid (iat)")
jwt.exceptions.ImmatureSignatureError: The token is not yet valid (iat)

The line payload["iat"]=1674086508.2282877 now=1674086508 is a custom print() I added in the code for debugging. That JWT being validated is the token= passed in the interactive URL, it's not the SEP-10 token. Apparently, if the popup is opened in the same second as the interactive URL is returned from the Anchor, the JWT iat value (payload["iat"], generated by Polaris) can, sometimes, can be higher than now (generated by api_jwt.py) when validating the token. That generates the The token is not yet valid (iat) error in the screenshot. Also, iat is a float (Polaris generates it using time.time()) and now is int. Sometimes due to rounding, iat might end up rounding up instead of down, becoming one second higher than now, which generates the error.

The error only happens if the Wallet opens the popup very quickly. A workaround is for Wallets to wait a second or two before opening the popup, which is not ideal.

So, a suggestion to fix this issue, is for Polaris to do something like iat = int(time.time()) - 1, which would make iat be one second earlier, making it impossible for that error to occur.