I am trying to set a cookie from a response when using the scala play framework. I am creating a cookie called session with its value being a UUID (I do know play comes with its own session management).
I can see the response headers contain the set cookie instruction, but the cookie ins't being set.
Below is the scala code in the action in the controller where the cookie is set
val cookie= Cookie("session",
sessionToken,
httpOnly=true,
sameSite=Some(Cookie.SameSite.Lax))
Ok(Json.toJson(res))
.withCookies(cookie)
// Also tried with .bakeCookies() after the withCookies() call
I can see the cookie header in the response in both FireFox and Chrome. They both show what appears to be a correctly formed cookie in their respective response cookie viewer in their developer tools.
Set-Cookie: session=c0174ed1-ebd3-4a8d-a5b2-5b09a3fe616b; SameSite=Lax; Path=/; HTTPOnly
However, in both browsers the cookie does not get set. I have tried true and false httpOnly, and messing with the maxAge value. I have tried setting the domain to a url and then setting the url in the hosts file as suggested here.
The URL on the react frontend is
http://localhost:49161/login/hydrate
and the endpoint in play is
http://localhost:49162/user/login/rehydrate
I did also try setting the path to /login/hydrate/ on the cookie
The react code on the front end
// Inside async function
// methodStrings[method] = "post" in this request
axios[methodStrings[method]](url, params)
.then(result => {
resolve(result);
})
.catch(err => {
console.error(`Error with request to ${url} - ${err}`);
reject(err.response.status);
});
And then I console.log the result from awaiting the request
Problem is in axios (and/or browser).
Based on this issue Cookies headers are present but Cookies are not stored in browser #1553 you need to set withCredentials Axios config to store cookies in browser after request:
axios.post('domain.com', {
name: 'name',
password: 'password'
}, {
//AxiosRequestConfig parameter
withCredentials: true //correct
})
Related
There is a server, which serves my client react app at root path. So when I make any request to server from POSTMAN, to login for example, cookies are attached perfect. But when I make request from my client using AXIOS and withCredentials field as well, cookies ain't attached, nevertheless the request is sent good, but no cookies received. I don't think there is any reason to search issues in server code, because postman works with it perfect. In case, there is no CORS errors: server provides client app. I get nice response from the server, with no cookies. Postman gets them.
axios request in react app:
export const login = createAsyncThunk(
'auth/login',
async (credentials: ILogin) => {
// todo: making a request to server
const response = await axios({
url: '/api' + '/auth' + '/login',
method: 'POST',
data: credentials,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
},
});
console.log(response)
}
)
Client doesn't receive cookies, neither on localhost nor deployed app.
As you see, only place where cookies are shown it's network section in devtools, but everything else, including server acts like my second request hadn't any cookie, because in this case, server would answer like: agh, already logged in
P.S: i'm using http
How to get access to cookies that I get in the response of axios post and get request, Am using WooCommerce Rest API and I need the access to PHPSESSID that I get on response, I tried on postman as it automatically set the cookie to header, Is there anyway to do in React JS?
The fetch API allows you to read the response headers of a request:
const getResponse = async () => {
const response = await fetch("https://stackoverflow.com/");
// log all response headers
console.log([...response.headers.entries()])
// look for set-cookie
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
console.log(response.headers.get("set-cookie"));
}
However this will only work if the WooCommerce Rest API will set or modify the cookie exactly in that response.
I'm trying to send cookie from the server to the react app and use this cookie as auth in the middleware. With the postman, everything is working, but in the browser, it is not.
As I have read some tutorials I need to set up cors and here is the snippet of my server-side app.
app.use(cors({ origin: "http://localhost:3000/", credentials: true }));
res.status(200).cookie("login_auth", token, { httpOnly: true, domain: "http://localhost:3000" }).json({ user });
Then I'm sending the post request
axios.post("http://localhost:5000/user/login", { email, password }, { withCredentials: true })
but when I check the cookie storage for my app there is no cookie and further, I have no idea how to send the cookie back to the server to fulfill the middleware. In postman it is all done so easily.
I can save the cookie with the "js-cookie", but I don't think it is the right way to do it.
Cookies.set("login_auth", response.data.token);
Somebody help?
Problem
I'm trying to use server side session (saved on PSQL db) but they are not persisting in between the requests.
Description
I'm running my application locally and is of two parts.
Backend running on MY_IP:2501
Frontend running on MY_IP:3000
Now as per my understanding, Flask saves the session in the "session" table of PSQL (since we are storing server side sessions) and the ID from that particular row is sent to the client in the form of a response header i.e. "Set-Cookie".
Every thing described above is working, but when the React frontend (or browser) receives this header it doesn't creates a cookie out of it because of which the session id is not stored in the frontend and then the frontend is unable to send the same to the backend due to which it is not able to fetch the associated session data resulting in empty session every time.
:(
Stuff I've tried so far..
Done allowing all type of headers while returning the response.
`response.headers.add('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept, x-auth")`
Done allowing the withCredentials header attribute from front end as well as backend.
Removed HttpOnly parameters from the session using "SESSION_COOKIE_HTTPONLY" config property
Done setting the "SESSION_COOKIE_DOMAIN" same as the front end
NOTE
If I call my API via POSTMAN the session is persisting as the cookie is saved in POSTMAN.
If I run the application on chrome --disable-web-security, then also it works.
Only configuration that is required:
Send the request (REST / GraphQL) with the header withCredentials = true.
Add Access-Control-Allow-Credentials = true headers from the backend.
On Axios (Frontend REST API).
import axios from 'axios';
export const restApi = axios.create({
baseURL: urlBuilder.REST,
withCredentials: true
});
restApi.interceptors.request.use(
function(config) {
config.headers.withCredentials = true; # Sending request with credentials
return config;
},
function(err) {
return Promise.reject(err);
}
);
On Apollo (Frontend GraphQL)
import {
ApolloClient,
ApolloLink
} from 'apollo-boost';
const authLink = new ApolloLink((operation, forward) => {
operation.setContext({
fetchOptions: {
credentials: 'include' . # Sending request with credentials
}
});
return forward(operation);
});
On Python-Flask (Backend)
#app.after_request
def middleware_for_response(response):
# Allowing the credentials in the response.
response.headers.add('Access-Control-Allow-Credentials', 'true')
return response
I've been trying to make an React site, which would fetch a GET-response from API and print it out to my .html-file. I've managed to fetch the file just right, but i can't access the JSON-data server sends me.
If i use no-cors in my Fetch-request, i get an opaque response containing pretty much nothing, but if i go to Developer tools i can find my data there and read it. If i do use cors, almost same thing. I get an 403-error, but my data is in the browser memory, but my code doesn't print it out. I can find the response from Network in developer tools.
Why does the server give me an error, but still i get my data? And how can i access it, if it's in the browser?
class Clock extends React.Component {
constructor(props) {
super(props)
this.state = {data2: []}
this.apihaku = this.apihaku.bind(this)
}
componentDidMount() {
this.apihaku(),
console.log("Hei")
}
apihaku () {
fetch('https://#######/mapi/profile/',
{method: 'GET', mode:'no-cors', credentials: 'include',
headers: {Accept: 'application/json'}}
).then((response) => {
console.log(response);
response.json().then((data) =>{
console.log(data);
});
});
}
render() {
return <div>
<button>Button</button>
</div>
}}
ReactDOM.render(
<Clock />,
document.getElementById('content')
)
EDIT: Error images after trying out suggestions
https://i.stack.imgur.com/wp693.png
https://i.stack.imgur.com/07rSG.png
https://i.stack.imgur.com/XwZsR.png
You're getting an opaque response, because you're using fetch with mode: 'no-cors'. You need to use mode: 'cors' and the server needs to send the required CORS headers in order to access the response.
Fetch is doing exactly what the documentation says it's supposed to do, from Mozilla:
The fetch specification differs from jQuery.ajax() in two main ways:
The Promise returned from fetch() won’t reject on HTTP error status
even if the response is an HTTP 404 or 500. Instead, it will resolve
normally (with ok status set to false), and it will only reject on
network failure or if anything prevented the request from completing.
By default, fetch won't send or receive any cookies from the server,
resulting in unauthenticated requests if the site relies on
maintaining a user session (to send cookies, the credentials init
option must be set). Since Aug 25, 2017. The spec changed the default
credentials policy to same-origin. Firefox changed since 61.0b13.
So you need to use CORS, otherwise you get an opaque response (no JSON), and then 403 to me suggests that you haven't authenticated properly. Test your API with Postman, if I had to take a guess I'd say the API isn't sending the cookie because it's a GET request, so no matter how well you set your headers on the client it won't work. Try it as a POST instead. GET requests should really only be used to drop the initial HTML in the browser. I think for your headers use these, include the creds that the API sends and allow the domain to be different.
mode: "cors", // no-cors, cors, *same-origin *=default
credentials: "include", // *same-origin
Try this and see where is the error happening i believe in the parsing but lets check and see
fetch(https://#######/mapi/profile/, {
method: "GET",
headers: {
"Content-Type": "application/json"
},
credentials: "include"
})
.then((response) => {
console.log(response);
try {
JSON.parse(response)
}
catch(err){
console.log("parsing err ",err)
}
})
.catch((err)=>{
console.log("err ",err)
});
I had a similar issue, this kind of problem happend when a HTTP port try to send request to a HTTPS endpoint, adding a "mode:'no-cors'" doesn't do what is SOUND doing but rathere when the documentation says.
I fixed the issue by allowing in my API Application for calls from my HTTP port
(i'm using a .net 6 as an API in debugging mode, my code look like this https://stackoverflow.com/a/31942128/9570006)