user7197914 user7197914 - 1 year ago 129
Python Question

TypeError: Expecting a string- or bytes-formatted key when using Flask-JWT

I have a question about flask python.
I tried learning how to build a web using flask, and there is some error. In this case I am using mongoengine as database and JWT(Json Web Token) and the alert error is like this: "TypeError: Expecting a string- or bytes-formatted key" - - [22/Nov/2016 22:50:08] "POST /auth HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1639, in full_dispatch_request
rv = self.dispatch_request()
File "/home/def/.local/lib/python2.7/site-packages/flask/", line 1625, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/def/pr/flask/flask_deeper/test/routes/", line 26, in auth
access_token = _jwt.jwt_encode_callback(identity)
File "/usr/local/lib/python2.7/dist-packages/flask_jwt/", line 70, in _default_jwt_encode_handler
return jwt.encode(payload, secret, algorithm=algorithm, headers=headers)
File "/usr/local/lib/python2.7/dist-packages/jwt/", line 56, in encode
json_payload, key, algorithm, headers, json_encoder
File "/usr/local/lib/python2.7/dist-packages/jwt/", line 98, in encode
key = alg_obj.prepare_key(key)
File "/usr/local/lib/python2.7/dist-packages/jwt/", line 116, in prepare_key
raise TypeError('Expecting a string- or bytes-formatted key.')
TypeError: Expecting a string- or bytes-formatted key.

I thought the error was at this.


def jwt_handler(token):
if not User.objects(token=token):
raise JWTError("Bad bad bad bad")

secret = str(current_app.config["JWT_SECRET_KEY"])
algorithm = str(current_app.config["JWT_ALGORITHM"])
options = {
'verify_' + claim: True
for claim in verify_claims

'require_' + claim: True
for claim in required_claims

decode = jwt.decode(token, secret, options=options, algorithms=[algorithm])
return decode

def authenticate(username, password):
user = User.objects(username=username)
if len(user) == 0:
return None
user = user[0]
user["id"] = str(user["id"])

if crypt.verify(password, user.password):
return user

return user


def auth():
username = request.form.get("username")
password = request.form.get("password")

if not username:
raise BadRequest("Userna doesn't exists")

user =

identity = _jwt.authentication_callback(username, password)

if identity:
access_token = _jwt.jwt_encode_callback(identity)
return _jwt.auth_response_callback(access_token, identity)
raise JWTError("Bad bad bad very bad")

import os
from test.models import db

class Config(object):

db_name = os.getenv('MONGODB_NAME', 'third')
db_host = os.getenv('MONGODB_HOST', '')
db_port = os.getenv('MONGODB_PORT', '5000')

JWT_SECRET_KEY = 'test123'

import logging.config
import jwt
from flask_jwt import JWT
from flask import Flask

from test import routes
from test.models import db, User

_jwt = JWT(authentication_handler=User.authenticate, identity_handler=User.identity)

def create_app(config):
app = Flask(__name__.split(',')[0])




return app

Answer Source

You have defined the configuration is but have not added the configuration object to your flask app. Therefore, keys such as JWT_SECRET_KEY are not in your app config.

Flask-JWT's default_handler expects those values (Copied in case source changes)

def _default_jwt_decode_handler(token):
    secret = current_app.config['JWT_SECRET_KEY']
    algorithm = current_app.config['JWT_ALGORITHM']
    leeway = current_app.config['JWT_LEEWAY']

In your case as that is not set, it returns None and trips the (which expects a string key).

Therefore, during your app initialization in, you must add a call to app.config.from_object. Maybe something like this

def create_app(config):
    app = Flask(__name__.split(',')[0])

    # Edit the following to point it to your Config class




    return app

On a side note, the name of JWT_ALGORITHM should be HS256 rather than SH256 (Although it doesn't matter as HS256 is the default and will be chosen since SH256 is not a valid algorithm)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download