I have created a basic application using flask, sqlite3, sqlalchemy and JWT for user authentication. My decorator is as follows [please excuse the formatting i assure you the indentation is correct in the code]:
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = None
print(request.headers)
if 'x_access_token' in request.headers:
token = request.headers['X-Access-Token']
if not token:
return jsonify({'message' : 'Token is missing.'}), 401
try:
data = jwt.decode(token, SECRET_KEY)
current_user = User.query.filter_by(public_id=data['public_id']).first()
except:
return jsonify({'message': 'Token is invalid.'}), 401
return f(current_user, *args, **kwargs)
return decorated
My main login route is where i ask for a username and password, and if that works i pass along a jwt token in the header to my routes that require a token:
@Main.route('/login', methods=['GET', 'POST'])
def login():
auth = request.authorization
if not auth or not auth.username or not auth.password:
return make_response('Could not verify!', 401, {'WWW-Authenticate' : 'Basic realm="Login Required!"'})
user = User.query.filter_by(username=auth.username).first()
if not user:
return make_response('Could not verify!', 401, {'WWW-Authenticate': 'Basic realm="Incorrect username"'})
if check_password_hash(user.password, auth.password):
token = jwt.encode({'public_id' : user.public_id,
'exp' : datetime.datetime.utcnow() + datetime.timedelta(seconds=5000)},
SECRET_KEY)
response = redirect(url_for('Main.views'))
response.headers['X-Access-Token'] = token.decode('UTF-8')
print('hi', response.headers)
return response
# return response_builder('Main.views', token)
else:
return make_response('Could not verify!', 401, {'WWW-Authenticate': 'Basic realm="Incorrect password"'})
But when my route called views is opening it cant find the token in the header causing the else part of my decorator to be executed i.e. missing token.
I printed out the headers i send in my response from /login:
Content-Type: text/html; charset=utf-8
Content-Length: 219
Location: /views
X-Access-Token: [a long hashed value]
And when i print the headers in the decorator for my view that login redirects to there is no x-access-token!
Host: localhost:5000
Connection: keep-alive
Cache-Control: max-age=0
Authorization: Basic YWJoaTphYmhp
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/83.0.4103.61 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;
q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: Pycharm-6d7a12e6=5d65ff91-afab-45ec-8de8-a23e44c046dd; __test=1; username-localhost-
8888="2|1:0|10:1590510962|23:username-localhost-
8888|44:MTA2YjkyMWJiMmU2NDU1MGFmM2Q5MjZhZGE5YjEwODA=|
f3ea838f5405f6c102ddbaf45dfef9bd000d2d183eaba9310d698d1005a6c21b";
session=eyJkYl9uYW1lIjoibXlfaGlzdCJ9.Xt-9aA.vDjCIXn731CioU72zCiJFim1shg
This is my view that requires a token:
# views page for navigation
@Main.route('/views')
@token_required
def views(current_user):
print(current_user)
return render_template('Main/Views.html')
Another method i tried instead of redirect is make_response and that dint work either, it seems to just skip the decorator and render /views on the page. Not the html of /views but literally /views