pallets-eco / flask-security

Quick and simple security for Flask applications
MIT License
1.63k stars 513 forks source link

Redirect failing after login from VueJS using Axios #848

Open fuck-usa-restrictions opened 4 years ago

fuck-usa-restrictions commented 4 years ago

When I try to login a user from VueJS/Axios (against the /login route from Flask-Security), Flask fails to redirect me once the login succeeds.

I removed WTF_CSRF to make the login only dependent on the user's email and password. Here my config:

class DevConfig:

    FLASK_DEBUG = True
    SECRET_KEY = 'super-secret'
    SECURITY_PASSWORD_SALT = 'some arbitrary super secret string'
    WTF_CSRF_ENABLED = False
    WTF_CSRF_CHECK_DEFAULT = False

    MONGODB_DB = 'mydatabase'
    MONGODB_HOST = 'localhost'
    MONGODB_PORT = 27017

Then, I tested the endpoint using Postman to make sure I was able to login properly against the /login endpoint, and it works just as expected.

This is the endpoint I'm expecting to redirect to after successfully login in...

# Views
@app_routes.route('/', methods=['GET', 'POST'])
@login_required
def home():
    user = current_user.get_security_payload()
    print(user)
    roles = user["roles"]
    for role in roles:
        print(role.get_security_payload())
    return("CURRENTLY LOGGED")

This is the result from Postman after sending the POST request to the /login endpoint (Exactly the one I'm expecting)

enter image description here

When I check the flask's server logs after the request with Postman, this is what I see:

enter image description here

As you can see, as I successfully provided the user credentials to the /login endpoint, I was redirected to the route /. However, when I attempt to do the same from my VueJS frontend using axios, although I'm successfully redirected to the / route, a second redirect occurs, sending me back to the /login route, as you can check in the logs:

enter image description here

This is how my axios' call from Vue looks like:

formSubmit() {
      let currentObj = this;
      const formData = new FormData();
      formData.append("email", this.user.username);
      formData.append("password", this.user.password);
      formData.append("submit", "Login");
      this.axios.post('http://localhost:5000/login', formData)
      .then(function (response) {
        console.log(response.data);
      })
      .catch(function (error) {
        console.log(error);
      });
    }

First, I thought that maybe the form being send by axios didn't have the right format, but I checked, the form sent by Postman and the one sent by axios look exactly the same. (the first log is the form received by Flask's server from postman and the second one the form received from axios/vue):

enter image description here

I also considered that maybe, for some reason, Vue wasn't allowing the redirect, so I added two new endpoints to my backend just for testing the redirect:

@app_routes.route('/redirected')
def redirected():
    return "REDIRECTED"

@app_routes.route('/redirect', methods=['GET', 'POST'])
def redirecting():
    return redirect(url_for('app_routes.redirected'))

I changed the axios request URL to /redirect and I was successfully redirected. So obviously this is not a problem from Vue/Axios side, but from Flask side.

Why this isn't working?

jwag956 commented 4 years ago

My guess is the second redirect is occuring due to @login_required - i.e. - although you successfully logged in - when the redirect happens to "/" it doesn't think you are logged in. This could be because axios isn't sending the session cookie - I don't know why that would be. Try opening up dev tools in your browser where you are using axios and look for the response cookie from /login and make sure it is getting sent...