I have a log-in page which makes a request to my server, which sets a session cookie and redirects to a dashboard page. On the log-in page, I can verify the cookie gets set correctly after sending credentials, and it will persist when I manually click on links to navigate around the site (as expected).
However, when I try to automatically redirect to the dashboard after the log-in function succeeds, my cookie is unset and I cannot figure out where it has gone. I have tried managing the redirect via document.location
/window.location
with the different .href
/.path
/.url
fields, but the cookie is gone after calling any of those or refreshing the page.
I'm using self-signed HTTPS 127.0.0.1
with CORS (I am no longer receiving CORS errors after lots of headache, so I don't think the problem is there, especially since I can see it exists without the redirect). Also, I'm using Svelte as the front-end and Axum (Rust) as my back-end, if that's important at all.
Why does my cookie get "eaten" when trying to force-redirect the user to another page?
request method:
await fetch('https://localhost:4000/users', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: `{ "email": "${email}", "password": "${await hash}" }`
});
// cookie exists if this line is removed
document.location.href = '/dashboard';
// cookie is gone when the new page loads
server config (Axum):
let server = axum_server::bind_rustls(
SocketAddr::from(([127, 0, 0, 1], 4000)),
tls_config,
)
.serve(
Router::new()
.route("/", get(root))
.layer(
CorsLayer::new()
.allow_headers([
header::CONTENT_TYPE,
header::CONTENT_LENGTH,
header::COOKIE,
header::SET_COOKIE,
])
.allow_methods([
Method::GET,
Method::HEAD,
Method::OPTIONS,
Method::DELETE,
Method::POST,
])
.allow_origin([
HeaderValue::from_str("http://127.0.0.1:3000").unwrap(),
HeaderValue::from_str("https://127.0.0.1:3000").unwrap(),
])
.allow_credentials(true),
)
.into_make_service(),
);
response headers:
HTTP/2 200 OK
content-type: application/json
set-cookie: session=1234; Path=/; HttpOnly; SameSite=None; Secure
content-length: 26
access-control-allow-origin: https://127.0.0.1:3000
access-control-allow-credentials: true
vary: origin
vary: access-control-request-method
vary: access-control-request-headers
date: Tue, 07 Jun 2022 01:56:11 GMT
CodePudding user response:
I ended up replacing my fetch
calls with axios
calls and it works as expected now. I still don't know if I was using it wrong, but these look like they'd be pretty identical to me...
await fetch('https://localhost:4000/users', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: `{ "email": "${email}", "password": "${await hash}" }`
});
await axios.post('https://localhost:4000/users', {
email: email,
password: await hash,
}, {
withCredentials: true
});
If somebody is able to explain what the difference is, I'd be super interested :)