Closed lilz-egoto closed 1 month ago
So just to be clear - using JSON or forms is completely independent of how you authorize/authenticate. The XSRF-Token is for CSRF protection - not authentication. Sounds like somehow the session cookie isn't being sent. Would need some code snippet to provide more insight.
I can confirm that I get sent a session cookie from flask once I login/register and is valid since I can setup/disable 2FA with it.
flask config:
app.config["SESSION_COOKIE_SAMESITE"] = "Strict"
app.config["SESSION_COOKIE_HTTPONLY"] = True
app.config["SESSION_COOKIE_SECURE"] = True
app.config["SECURITY_CSRF_COOKIE_NAME"] = "XSRF-TOKEN"
app.config["SECURITY_CSRF_HEADER"] = "X-XSRF-Token"
app.config["SECURITY_CSRF_PROTECT_MECHANISMS"] = ["session"]
app.config["SECURITY_CHANGEABLE"] = True
app.config["SECURITY_CHANGE_URL"] = "/change"
The frontend looks like this:
await axios(URL, {
method: "GET",
withCredentials: true,
headers: {
Accept: "application/json",
},
})
.then((response) => {
this.csrf_token = response.data.response.csrf_token;
}
await axios(URL, {
data: data,
method: "POST",
withCredentials: true,
headers: {
"Content-Type": "application/json",
"X-XSRF-Token": this.csrf_token,
},
})
I include X-XSRF-Token since it says to here: https://flask-security-too.readthedocs.io/en/stable/_static/openapi_view.html#post-/change
For comparison the request headers for 2FA setup and change password. I think this shows I'm sending the cookie in both instances:
change:
2fa:
Nothing jumps out - especially since you say you can access other endpoints like 2fa. I am curious that you set the CHANGE_URL to "/change" which is the default... Of course some reproducible case would be great - I assume that the user you are trying to /change has an existing password? Barring that - a more complete set of headers and body (including URL) would be good.
const data = {
password: this.password,
new_password: this.new_password,
new_password_confirm: this.new_password_confirm,
};
More headers, including URL:
tf_setup is a bit odd since it supports being called whether the caller is authenticated or not. Looking at the code its possible it has a bug in the authenticated case where it isn't properly checking CSRF. I'll look into that.
I am wondering whether the caller is actually authenticated - could you go here: https://www.kirsle.net/wizards/flask-session.cgi and cut-paste in your session cookie contents - lets see what's there.
I deleted my cookies and logged back in. The first one is before 2FA, second is after 2FA validation (just in case you wanted to see both)
{
"csrf_token": "65c92ed1a13d29c03020f411eacc0a30806cf203",
"tf_state": "ready",
"tf_user_id": "21db75026f2246e39f9ae439b7f95f28"
}
{
"_fresh": true,
"_id": "fd001fe1474e00d15677d374b44506f1c041384e870731386d2d09c93487ea1abf246de4705bc057cb9d7f4648a0a63ba7fd0cb70bcc6ce92a50fc6fcc63d626",
"_user_id": "21db75026f2246e39f9ae439b7f95f28",
"csrf_token": "65c92ed1a13d29c03020f411eacc0a30806cf203",
"fs_cc": "sent",
"fs_paa": 1705608186.4328818
}
All very odd - looks like the caller is in fact authenticated. All I can suggest is to start simplifying things - first - turn off CSRF (app.config["WTF_CSRF_ENABLED"] = False) (prior to initializing flask_security).
Did you change SECURITY_API_ENABLED_METHODS? could you show me your entire SECURITY config?
Sorry, it might be a few weeks until I can work on this again
My guess is that this is another manifestation of what we discovered with the session cookie being cleaned up on login GET. If this is still an issue - please re-open with more info. Thanks!
This is for the JSON API. Trying to set up the changeable endpoint, but the endpoint returns a 401 with the message "You are not authenticated. Please supply the correct credentials" even if I supply both the X-XSRF-Token and the session cookie. This happens with both GET and POST.
This does not happen with 2FA setup/disable where I similarly need the session cookie