Search code examples
pythoncredentialsopentokpython-venv

OpenTok constructor/create_session fails when not running venv


Running a Django rest api with Tokbox in a Debian Server. I was running it through a python virtual enviroment which was working fine, but need to take it out of the enviroment for a few reasons. When I did so, after installin all dependencies and got it running got the following error:

raise RequestError('Failed to create session: %s' % str(e))

opentok.exceptions.RequestError: Failed to create session: Failed to create session, invalid credentials

Both keys are saved as enviroment variables and brought back correctly, I can log them and they are correct. Also if I turn on the python virtual enviroment again the error disappears.

For the record, the lines of my code that cause the error are:

opentok = OpenTok(api_key, api_secret)
session = opentok.create_session(media_mode=MediaModes.routed)

The function that raises the exception in the source code is the following:

try:
        response = requests.post(self.session_url(), data=options, headers=self.headers(), proxies=self.proxies)
        response.encoding = 'utf-8'

if response.status_code == 403:
            raise AuthError('Failed to create session, invalid credentials')

At first I thought it had to be some sort of encryption or hashing that was done to the api key and api secret. And Tokbox does indeed use jwt for that, but it is done in a function called by the constructor and therefore also being done when I dont use the virtual enviroment. The function headers() called above in the request is the following:

def headers(self):
    """For internal use."""
    return {
        'User-Agent': 'OpenTok-Python-SDK/' + __version__ + ' ' + platform.python_version(),
        'X-OPENTOK-AUTH': self._create_jwt_auth_header()
    }

def _create_jwt_auth_header(self):
    payload = {
                  'ist': 'project',
                  'iss': self.api_key,
                  'iat': int(time.time()), # current time in unix time (seconds)
                  'exp': int(time.time()) + (60*3), # 3 minutes in the future (seconds)
                  'jti': '{0}'.format(0, random.random())
              }

    return jwt.encode(payload, self.api_secret, algorithm='HS256')

Solution

  • Server time seemed correct but I guess it wasn't. You can solve this by substracting some time from 'iat' in the jwt function. Ended up finding the solution thanks to tokbox support so props to them!

    Find where your installation placed the file 'opentok.py' by:

    find / -name opentok.py
    

    Then substract 3600 like the following lines show:

    def _create_jwt_auth_header(self):
        payload = {
                      'ist': 'project',
                      'iss': self.api_key,
                      'iat': int(time.time()) - 3600, # three minutes ago (seconds)
                      'exp': int(time.time()) + (60*3), # 3 minutes in the future (seconds)
                      'jti': '{0}'.format(0, random.random())
                  }
    
        return jwt.encode(payload, self.api_secret, algorithm='HS256')