0

I am trying to do a JWT token authorization using flask on the backend and Jquery, but Im having trouble implementing it.

I created a @token_required decorator and put it above the home ('/') route so that the only users with tokens can access it.

def token_required(func):
    @wraps(func)
    def decorated(*args,**kwargs):
        token = request.args.get('token')
        if not token:
            return jsonify({'Alert!' : 'Token is missing!'})
        try:
            payload = jwt.decode(token,SECRET_KEY)
        except:
            return jsonify({'Alert!' : 'Invalid token!'})
        return func(*args,**kwargs)
    return decorated
@app.route('/')
@token_required
def home():
    return "You are logged in"

Also I created a register and login functionality that return the token in json.

@app.route('/registerUser',methods=['GET', 'POST'])
def registerUser():
    conn = mysql.connect()
    cursor = conn.cursor()
    if request.method == 'POST':
        data = request.get_json()
        username = data['username']
        email = data['email']
        password = data['password']
        confirm_password = data['confirmPassword']

        if password == confirm_password:
            password = generate_password_hash( data['password'],method="sha256")
            if isRegistered(email):
                return make_response("Email already exists",409)
            else:
                query_string = "INSERT INTO users_eg(username,email,password)VALUES(%s,%s,%s);"
                cursor.execute(query_string, (username,email,password))
                conn.commit()
                token = jwt.encode({
                    'user':data['email'],
                    'expiration': str(datetime.utcnow() + timedelta(minutes=30))
                },
                SECRET_KEY)
                return make_response(jsonify({'token' : token}),201) #I need to redirect the user to home route here. 
        else:
            return make_response("Check confirm password again",400)
@app.route('/loginUser',methods=['GET', 'POST'])
def loginUser():
    if request.method == 'POST':
        data = request.get_json()
        email = data['email']
        password = data['password']
        if isRegistered(email):
            if checkPassword(password):       
                token = jwt.encode({
                    'user':data['email'],
                    'expiration': str(datetime.utcnow() + timedelta(minutes=30))
                },
                SECRET_KEY)

                return make_response(jsonify({'token' : token}),200) #I need to redirect the user to home route here. 
            else:
                return make_response("Password is incorrect",400)
        else:
            return make_response("Email doesn't exist",400)

From the token returned from both login and register, what do I do with it to get access to the protected route ? Do I need to fetch it from the frontend and put it in headers when logging in?

If you send token through headers from the frontend, does it automatically get checked if the token is valid or not by the decorator function?

I have alot of questions here. sorry.

I tried this on my frontend. Im guessing its wrong as I didn't really know what to do in the frontend. I used localStorage to keep my token, but I am guessing this won't work unless I use react or something.

Registering

 $(document).ready(function () {
        $("form").on("submit", function (event) {
          const userInfo = {
            username: $("#username").val(),
            email: $("#email").val(),
            password: $("#password").val(),
            confirmPassword: $("#confirmPassword").val(),
          };
          $.ajax({
            type: "post",
            url: "http://127.0.0.1:5000//registerUser",
            dataType: "json",
            contentType: "application/json",
            data: JSON.stringify(userInfo),
            success: function (result) {
              localStorage.setItem("token", JSON.parse(result.token));
            },
            headers: {
              Authorization: "Bearer " + localStorage.getItem("token"),
            }
          });
          event.preventDefault();
        });
      });

Login

 $(document).ready(function () {
        $("form").on("submit", function (event) {
          const userInfo = {
            email: $("#email").val(),
            password: $("#password").val(),
          };
          $.ajax({
            type: "get",
            url: "http://127.0.0.1:5000//loginUser",
            dataType: "json",
            contentType: "application/json",
            data: JSON.stringify(userInfo),
            success: function (result) {
              localStorage.setItem(JSON.parse(result.token));
            },
            headers: {
              Authorization: "Bearer " + localStorage.getItem("token"),
            },
          });
          event.preventDefault();
        });
      });
zyus
  • 1
  • 2
  • 1. You are passing your token as an `Authorization` header and for some reason expecting it in `token` query parameter. 2. What is the point of `JSON.parse(result.token)`? Are you trying to parse JWT via JSON parser? 3. expiration time [is better to be set as `exp` not `expiration`](https://stackoverflow.com/questions/39926104/what-format-is-the-exp-expiration-time-claim-in-a-jwt) – sudden_appearance Apr 18 '23 at 17:23
  • request.args.get('token') is incorrect. The token comes in as a header (Authorization: Bearer token) as is shown in your other code. – John Williams Apr 18 '23 at 17:31
  • In that case, is request.headers the option to go with? – zyus Apr 18 '23 at 17:32
  • After the token is expired, there needs to be a way to get the token from backend again. That is why I am passing the token as an Authorization header and expecting token as well so that everytime i login, i get a new token. I know this is kinda weird but I didn`t know the other way to do it. Would it be better to store the token in session variable on flask? – zyus Apr 18 '23 at 17:38

0 Answers0