'flask jwt extended with status code 401 in React frontend
I am using Flask-JWT-Extended, and Flask CORS with React to make a web app. According to the documents of Flask-JWT-Extended which provide the "Protected" route to check the JWT token. I can use Axios get to get the protected route successfully but can't succeed in Axios post request ( The post request can be sent through Postman successfully).
I have two questions.
- How can I succeed to post a request to the Flask backend from React. When I used Postman, the post request is okay but it's not okay in React (Request failed with status code 401) and (Missing JWT in headers, cookies, json or query_str…key in json data)
(Solved, just the headers position in wrong a place)
- Since the token sent to frontend by Flask is an HTTP-only cookie. How does Axios send the post header with "access_token_cookie"
Flask- app.py
from textwrap import indent
from flask import Flask, request, jsonify, redirect, Response
import pymongo
from pymongo import MongoClient
from pymongo import ReturnDocument
import json
# MongoDB use bson
from bson import json_util
from bson.json_util import dumps, loads
# Flask JWT Extended
from flask_jwt_extended import create_access_token
from flask_jwt_extended import jwt_required
from flask_jwt_extended import JWTManager
from flask_jwt_extended import set_access_cookies
from flask_jwt_extended import set_refresh_cookies
from flask_jwt_extended import unset_jwt_cookies
from flask_jwt_extended import get_jwt_identity
from flask_jwt_extended import create_refresh_token
from datetime import timedelta
from flask_cors import CORS, cross_origin
# Hash the password
from flask_bcrypt import Bcrypt
# MongoDB setup
cluster = MongoClient("API_KEY")
db = cluster["UserData"]
user_collection = db["user_collection"]
post_collection = db["post_collection"]
test_collection = db["test_collecction"]
user_collection.create_index('username',unique=True)
app = Flask(__name__)
app.config["JWT_TOKEN_LOCATION"] = ["headers", "cookies", "json", "query_string"]
app.config["JWT_COOKIE_SECURE"] = False
app.config["JWT_SECRET_KEY"] = "super-secret"
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=1)
app.config['JWT_COOKIE_CSRF_PROTECT'] = False
app.config["JWT_CSRF_METHODS"] = [ "POST","PUT", "PATCH", "DELETE"]
app.config['JWT_ACCESS_COOKIE_PATH'] = '/'
CORS(app, supports_credentials=True)
bcrypt = Bcrypt(app)
jwt = JWTManager(app)
@app.route("/login", methods=["POST"])
def login_user():
request_payload = request.json #if the key doesnt exist, it will return a None
userData = request_payload['user']
# Find DB data
try:
existing_user = user_collection.find_one({"username": userData["username"]})
except:
return f"error! Database cannot be connected"
# If found user, check password
if existing_user:
input_password = userData["password"]
database_password = existing_user["password"]
# If match,will return true
if bcrypt.check_password_hash(database_password, input_password):
username_variable= existing_user["username"]
access_token = create_access_token(identity=username_variable)
response = jsonify({"msg": access_token},{"Welcome": username_variable})
set_access_cookies(response, access_token)
return response
else:
return("password not match")
else:
return f"no_such_user"
@app.route("/protected", methods=["GET", "POST"])
@jwt_required()
def protected():
getTheLoginNameFromToken= get_jwt_identity()
return jsonify({"Congratulations, Login successful, you are": getTheLoginNameFromToken})
@app.route("/post", methods=["POST"])
@jwt_required()
def createpost():
if request.method =="POST":
request_payload = request.json #if the key doesnt exist, it will return a None
print(request_payload)
post_collection.insert_one(request_payload)
return f"Post has been saved"
Post request function(React) not work
const submitApplication = (e) => {
e.preventDefault();
axios
.post(`${API_URL}/post`, {
headers: {
"Content-Type": "application/json",
Authorization:
"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY1MjQ3MDI0MywianRpIjoiMjE3NWI3MTYtYjJiZS00OTFhLWI5MTYtZjVlMzQzN2UxZTJlIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImFkbWluIiwibmJmIjoxNjUyNDcwMjQzLCJleHAiOjE2NTI0NzM4NDN9.AZyzOBlNimaAVQ26ZwKBgzw3TUTncBRUpbi0FOJwAg8",
},
title: title,
description: description,
content: content,
slug: slug,
imageLink: imageLink,
category: {
slug: category,
id: category,
},
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
console.log(error.response.data);
});
};
Post request function(React) work
const submitLogin = (e) => {
e.preventDefault();
axios
.post(
`${API_URL}/login`,
{
user: {
username: username,
password: password,
},
},
{ withCredentials: true, credentials: "include" }
)
.then(function (response) {
// the access token will store in cookies automatically (http-only cookie)
Cookies.set("username", `${response.data[1].Welcome}`);
// Redirect original page
setTimeout(function () {
window.location.replace("/login");
}, 500);
})
.catch(function (error) {
console.log(error);
});
};
Updated: Q1 solution
const submitApplication = (e) => {
e.preventDefault();
axios
.post(
`${API_URL}/post`,
{
title: title,
description: description,
content: content,
slug: slug,
imageLink: imageLink,
category: {
slug: category,
id: category,
},
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${tokenCode}`,
},
}
)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
console.log(error.response.data);
});
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|