11

I'm using Flask as my backend and jQuery for a personal project I'm working on.

To login I want to do this:

$.ajax({ 
    type: "POST",
    data: JSON.stringify(body), //username and password
    contentType: 'application/json; charset=utf-8',
    url: "/login",
    success: successFunction,
    error: errorFunction,
    complete: completeFunction
});

In the errorFuction I would tell the user that their username or password is incorrect etc.

On the backend my /login route looks like this

@app.route("/login", methods=['GET', 'POST'])
def login():
    if(request.method == "POST"):
        #retrieve the username and password sent
        data = request.json

        if(data is None or not 'username' in data or not 'password' in data):
            abort(400)
        else:
            count = User.query.filter(User.username == data['username']).count()
            if(count == 0):
                abort(404) #that user doesnt exist
            else:
                passIsCorrect = User.query.filter(User.username == data['username'],
                                                  User.password == data['password']).count()
                if(passIsCorrect):
                    session['user'] = data['username']
                    return redirect(url_for('index'))
                else:
                    abort(401)

    else:
        return render_template('login.html')

However on the client side, the browser doesn't redirect and if I look in the response object in the complete function I see what would normally be return from my '/' route: 200 OK and the index.html template.

My question is:

Is there some way I can intercept make the client redirect?

I assume the issue is because jquery is initiating the request and not the browser.

My first attempt at solving this problem was to construct the response myself using make_response and set the Location header but this resulted in the same behaviour. My current solution is to return 200 and then the client does window.location = "/", but this seems hacky

5
  • 4
    Why are you using AJAX if you want to duplicate the behavior of a regular form? Also, don't store plaintext passwords. Hash them. Commented Jun 22, 2013 at 8:51
  • You might want to have a look at Flask-Login for this task. It is probably going to be more secure than most self-built auth systems. Commented Jun 22, 2013 at 10:01
  • @Blender It's going to go over https eventually Commented Jun 22, 2013 at 10:24
  • 1
    @bio595: Doesn't make a difference. Hash them. Commented Jun 22, 2013 at 10:29
  • @Blender Also, using AJAX so that on error I can show() some error div Commented Jun 22, 2013 at 10:43

2 Answers 2

12

Redirects on ajax calls don't work, browsers do not honor them. Most people implement their own custom redirect solution, by returning code 200 and a URL to redirect to in the JSON response. See this question for some good examples.

As a side note, POSTing the login form via ajax does not really give you much of an advantage, I would let the browser POST the form normally and then your Flask view function redirects to a new page on success or redirects back to the login page on failure, possibly with a flash message to inform the user of the error.

Sign up to request clarification or add additional context in comments.

Comments

8

No reason use redirect with ajax because it will return redirected content (in your case just content with index endpoint). So you can return link to redirect if all ok (status 200) instead real redirect:

return url_for('index')

and process it with your js:

var successFunction = function (data) {
    // do something
    window.location = data;
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.