When users login, I send an axios post request to the login endpoint with its required credentials(accessToken). everything works fine. After a successful login, they are redirected to the homepage where I make i get request. The request doesn't send the credentials whixh of course would return an unauthenticated error. Even when I specify this in the axios get request it still woudn't work.
withCredentials: true
on postman and Insomnia, the token is sent successfully and the correct data is gotten, but It just will not work on the web. What could be wrong?
ths is the useFetch code
try {
await axios({
url: `https://crayonnne-jotter-server.herokuapp.com/api${url}`,
method: "get",
withCredentials: true,
}).then((res) => {
console.log(res)
});
} catch (err) {
console.log(err)
}
You have to provide the accessToken through the headers.
axios({
... // other stuff
headers: {
Authorization: `Bearer ${accessToken}`
},
})
Related
I am trying to set up authentication with Remix as my pure frontend and a django backend.
When the user signs in successfully, the backend sends a cookie with the response and this is set in the browser redirect with remix
const signIn = async (credentials: LoginCreds) => {
try {
const response = await fetch(generateFullBackendUrl('/auth/signin'), {
method: 'POST',
body: JSON.stringify(credentials),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
credentials: 'include'
});
return response;
} catch (e) {
console.log(e);
}
}
const response = await authService.signIn({
email,
password
})
const cookies = response?.headers.get('set-cookie');
if(cookies){
return redirect('profile', {
headers: {
'Set-Cookie': cookies
}
});
However when I try to make subsequent fetch calls in my loader the cookies are not sent to the backend as I would expect the browser would
await fetch(generateFullBackendUrl('api/users/me'), {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include'
})
Front end is running on port 3000
Backend running on port 4000
Im wondering why the fetch request in the loader does not send the cookies with the request
You need to read the cookie header from the loader request and pass it to your fetch headers.
There’s no way Fetch can automatically know what headers to send when used server side.
There is a quick workaround but not so elegant solution:
in your loader use this:
export const loader: LoaderFunction = async({request}) => {
const response = await fetch(`/api/books?${new URLSearchParams({
limit: '10',
page: '1',
})}`, {
headers: {
'Cookie': request.headers.get('Cookie') || ''
}
});
console.log(response)
if(response.ok) return await response.json();
}
I have a reactjs frontend running on root /.
On the same domain and server there is an Wordpress instance running under the default Wordpress slugs (/wp-admin, /wp-json, etc.). I already authenticate users via JWT over the WP API.
The problem is i need to get the Wordpress default auth cookies so users can switch between Wordpress and reactjs pages without logging in twice.
I started to add a second fetch on login which calls the /login.php route and posts login credentials as form-data. In Postman i get the body, headers and the auth cookies i need:
If i fetch this inside my react frontend i don't get the cookies, also the are not set and available under document.cookie or at the dev tools.
This is my fetch function in react which is returning the Dashboard Page as Response Data and a Status Code 200:
async handleCookies() {
const formData = new FormData()
formData.append('log', this.state.mail)
formData.append('pwd', this.state.password)
await fetch('XXX.XXX.XXX.XXX/wp-login.php', {
method: 'POST',
body: formData,
credentials: 'include',
headers: { 'Content-type': 'application/x-www-form-urlencoded', Cache: 'no-cache' },
})
.then(response => response)
.then(cookies => {
alert(cookies)
})
.catch(err => console.log(err))
}
Expectation: I expect to receive the cookies.
It turned out that i didn't passed the credentials in the right way. Now everything is working.
await fetch('XXX.XXX.XXX.XXX/wp-login.php', {
method: 'POST',
body: `log=${encodeURIComponent(EMAIL)}&pwd=${encodeURIComponent(PASSWORD)}`,
credentials: 'include',
headers: { 'Content-type': 'application/x-www-form-urlencoded', Cache: 'no-cache' },
})
I currently work with an api rest where I pass the controller parameters, version and action via URI. However, when I execute a request with URI with more than 19 characters, it gives this CORS error:
Access to XMLHttpRequest at 'http://my-api-host/toll/vehicle/v1/list' from origin 'http://localhost: 3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
In authentication the request works even with URI having more than 19 characters. However, any other request with a different URI that has more than 19 characters gives this same error. I use my application's API and the request works normally.
I'm using axios in Reactjs.
The api is already configuring to accept the content-type I am using (application / json) and is also already accepting requests from different sources.
My request code:
request(uri, params = {}){
return new Promise((resolve, reject) => {
axios
.post('http://my-api-host' + uri, JSON.stringify(params), {
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if (response.data.success) {
resolve(response.data);
} else {
reject(response.data);
}
});
});
};
Has anyone been through this and could help? thanks in advance
Did you use Fetch instead?
async function postData(url = '', params = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
headers: {
'Content-Type': 'application/json'
},
qs: JSON.stringify(params) // query string data
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('http://my-api-host', params)
.then(data => {
console.log(data);
});
I've been trying to get my frontend and backend to share cookies but the server never actually get them.
my frontend has credentials include on it
const res = await fetch('http://localhost:5000/v1/auth/register', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
and my backend have my core like
app.use(
cors({
origin: 'http://localhost:3000',
credentials: true,
})
);
and they still don't send cookies!
even tho I have a route that sets the cookie on the frontend from the backend
res.cookie('auth-token', token, {
httpOnly: true,
maxAge: 86400,
});
and it works perfectly fine after I used cors.
my check auth middleware:
exports.verifyAuth = async (req, res, next) => {
try {
const token = req.cookies['auth-token'];
if (!token) {
return res.status(401).json({ msg: 'No token, authorization required.' });
}
const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
req.user = decodedToken.user;
next();
} catch (err) {
res.status(401).json({ msg: 'No token, authorization required.' });
}
};
EDIT:
I was debugging it and apparently its always the first ever time that it doesn't send the cookies and that's because I'm using getInitialProps to send the request but I'm guessing that the request happens before cookies are loaded so I'm trying to find a way to pass the cookies to the request manually because fetch doesnt.
Try this config: {withCredentials: true}
I have a React app, and an API. When i POST data to APIs login url API responses me back with cookie on successful login, which I have to set, so in each next request user will send this cookie. But I can't find a method to get it from response.
I want to set sessionid, but I can't reach it within code. I tried to do
Cookies.set('sessionid', response.headers['sessionid']);
But it sets undefined. console.log(response.headers) also gives me {content-length: "31", content-type: "application/json"}. Do I do something wrong?
Sender function:
formSender() {
const url_to_send = `${this.state.api_base_url}:${this.state.api_base_port}${this.state.api_user_url}/login/`;
axios.post(url_to_send, `username=${this.state.username}&password=${this.state.password}`, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
.then((response) => {
// I need to set the cookie here
this.setState({
login_success: response.status === 200,
request_sent: false
});
})
};
Try to set Access-Control-Expose-Headers in the back end or
await axios({
method: 'post',
url: YOUR_URL,
data: Data,
headers: { 'Authorization': 'TOKEN' }
});
I have the same problems and i do that for resolve in backend:
app.use(cors({
origin: true,
credentials: true
}));
and the axios request :
axios({
method: "post",
url: `http://localhost:5500/api/user/login`,
withCredentials: true,
data: {
email,
password,
},
headers: {
"Content-Type": "application/json",
}
})
.then((res) => {
console.log(res);
})
I was initially looking for a solution to setting a cookie from a response, but I realized if it's passed as a Set-Cookie header then it is set by the browser. No need to set it manually. Here is the console view
My app looks something like this:
const app = express();
app.use(cors({
origin: ['http://localhost:3000'],
methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'HEAD'],
credentials: true,
}))
app.use(cookieParser())
app.get('/foo', verifyToken, (req, res) => {
// you can omit verifyToken if you want, it's for bearer auth.
if (true) {
res.cookie('XSRF-TOKEN', 'example')
res.send('Welcome')
} else {
res.sendStatus(403);
}
});
The React side:
<Button onClick={() => {
axios.get('http://localhost:8081/foo', {
params: {},
headers: {
Authorization: `Bearer 123`,
// again, omit ^ if you're not doing bearer auth
},
withCredentials: true,
}
).then((response) => {
console.log('cookie should be set')
})
}}>Express cookie</Button>
Bear in mind if you're deploying to a server both react and express should be on an https connection. Connecting http <-> https causes other issues with cookies.