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

Session token validation needs margin of error for nbf check #600

Closed
1 task done
adelespinasse opened this issue Aug 19, 2022 · 2 comments · Fixed by #609
Closed
1 task done

Session token validation needs margin of error for nbf check #600

adelespinasse opened this issue Aug 19, 2022 · 2 comments · Fixed by #609

Comments

@adelespinasse
Copy link

Issue summary

When App Bridge creates a session token (internal to the authenticatedFetch function), it apparently sets nbf to the current time according to the browser. This Python package (function session_token.decode_from_header) checks it against the current time on the server. So if the server's clock is slightly behind the browser's, validation fails.

Developers sometimes can't control how their server clocks are set, and they certainly can't control how browsers' clocks are set.

I don't know if the change should be made here or in App Bridge, but App Bridge's repo seems to be private, so I can't submit a bug report there.

Expected behavior

Either App Bridge should set nbf to a time somewhat in the past, or this Python API package should compare against a time somewhat in the future.

Actual behavior

What actually happens?

They both use the current clock time in their own environments. This often results in an error like the following:

Traceback (most recent call last):
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/shopify/session_token.py", line 52, in _decode_session_token
    return jwt.decode(
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/jwt/api_jwt.py", line 129, in decode
    decoded = self.decode_complete(jwt, key, algorithms, options, **kwargs)
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/jwt/api_jwt.py", line 116, in decode_complete
    self._validate_claims(payload, merged_options, **kwargs)
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/jwt/api_jwt.py", line 149, in _validate_claims
    self._validate_nbf(payload, now, leeway)
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/jwt/api_jwt.py", line 178, in _validate_nbf
    raise ImmatureSignatureError("The token is not yet valid (nbf)")
jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/aldel/gamalon/facetchat/facetchat/shopify_app.py", line 284, in check_config_access
    decoded_token = session_token.decode_from_header(
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/shopify/session_token.py", line 37, in decode_from_header
    decoded_payload = _decode_session_token(session_token, api_key, secret)
  File "/home/aldel/.local/share/virtualenvs/facetchat-WfgmyPlQ/lib/python3.9/site-packages/shopify/session_token.py", line 60, in _decode_session_token
    six.raise_from(SessionTokenError(str(exception)), exception)
  File "<string>", line 3, in raise_from
shopify.session_token.SessionTokenError: The token is not yet valid (nbf)

Steps to reproduce the problem

  1. Run an embedded app on a browser, connected to a server you control
  2. Set the server's clock 5 seconds behind the client's
  3. Have it make an API call using authenticatedFetch that is validated using session_token.decode_from_header

Checklist

  • I have described this issue in a way that is actionable (if possible)
@bp-xiao
Copy link
Contributor

bp-xiao commented Sep 27, 2022

Same here.

Note that Node.js' implementation also had the same problem and they fixed this by accepting 5 seconds clock skew.

see:

Here's my workaround:

import functools
from unittest import mock

LEEWAY_SECONDS = 5

# monkey patch jwt.decode() to accept clock skew
decode_from_header = mock.patch(
    "shopify.session_token.jwt.decode", functools.partial(jwt.decode, leeway=LEEWAY_SECONDS)
)(session_token.decode_from_header)

# usage
decode_from_header(
   authorization_header=request.META["HTTP_AUTHORIZATION"],
   api_key="xxx",
   secret="xxx",
)

@bp-xiao
Copy link
Contributor

bp-xiao commented Oct 3, 2022

This morning I opened a PR fixes this error.

andyw8 added a commit that referenced this issue Oct 17, 2022
…rror

#600 Fix: Accept 10 seconds clock skew to avoid `ImmatureSignatureError`
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

Successfully merging a pull request may close this issue.

2 participants