In my NodeJS Express app (built with feathers); I'm trying to work with cookies with client-side fetch from client javascript. I have Express using the cooke-parser middleware.
I have tried setting the credentials header to same-origin, but that has stopped working (it worked fine yesterday, and a few times today... but I've been trying to build up the cookie to what I need and it just doesn't seem to reliably work).
This is my test express route:
app.post('/setjwt', (req, res, next) => {
res.cookie('acokie', 'lol');
res.status(200);
res.send();
});
I'm using fetch in chrome dev tools console to test sending requests like so:
fetch('/setjwt', { method: 'POST', headers: { credentials: 'same-origin' } } );
These are the headers:
But there is no cookie listed in the Application tab nor available in document.cookie.
The reason I have this route is two fold:
Understand how cookies work and interop with Express.
Get rid of this hacky route altogether and get the headers/environment set up correctly so my feathers authentication service's Set-Cookie response header is respected by the browser.
The feathers client on the login page is set up with fetch as its rest implementation, and I can set
fetch('/setjwt', { method: 'POST', headers: { credentials: 'same-origin' } } ); won't work.
The credentials property cannot be specified like that with fetch. The correct code is:
fetch(
'/setjwt',
{
method: 'POST',
credentials: 'same-origin',
headers: { whatever: 'somevalue' }
});
As for setting it up so that the feathers authentication service would work, again, it's not a normal header so brushing up on the documentation hopefully might yield something useful, but I don't think the feathers-rest wrapper over fetch supports passing non header options.
Related
I currently have a web application that uses React frontend + Express sessions backend for authentication and authorization. I'm wondering if I can use the same or similar workflow for authenticating mobile users. This is how I authenticate users in my web application:
req.session.user = { id: user.rows[0].id }; // Set session cookie with user's ID
res.status(200).json({status: "success", message: "Login successful"});
It's very simple. If the passed login credentials are correct - I create a session with the user's ID that comes from the database and return a success to the front end.
Can I do something similar when using React Native as front end? I'm new to mobile development, but does the mobile client even have a cookie storage similar to a web browser? Very thankful for any input :)
Yes you can use cookies for authentication, I recommend to use fetch function to do http request. You need to pass access-control-allow-credentials header to share the cookies between server and client.
Example:
var params = {
method: "POST",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'access-control-allow-credentials': 'true'
}
}
params.body = JSON.stringify(body)
const response = await fetch(url, params)
const json = await response.json()
Call the exact same function from react native as it is from react and persist data using this library react-native-async-storage.
Here is my nodejs code that works perfectly with https site.
app.use(cors({ origin: '*' }));
app.use(express.json())
app.use("/user", userRouter);
app.use("/mention", mentionRouter);
app.use("/request", requestRouter);
But the problem is if I send the request from any HTTP site, I get an error saying TypeError: Failed to fetch and get no response. Here is my frontend code.
const response = await fetch(WEB_URL + "mention", {
method: "POST",
body: JSON.stringify({
to: users,
text,
link: window.location.toString(),
}),
headers: {
"x-access-token": accessToken,
"Content-Type": "application/json",
},
});
I tried answers from this Getting "TypeError: failed to fetch" when the request hasn't actually failed but not working.
Sorry to be one of those people, but your variables are not defined in your snippet so I can't really see what you have defined. Example:
const response = await fetch(WEB_URL + "mention",
Nobody knows what WEB_URL means and it can be apart of the problem.
Also, window.location can be used like http://example.com/, but it is an object so it could print "[object Object]". Instead, try using window.location.href. Your problem most likely is that the Fetch JS API is not available with HTTP sites for security reasons. There's not much more to the problem.
I am running a node.js app locally, in which I am trying to programmatically login into a server.
As shown in the figure, the login process consists of two steps. Firstly, when a user hits the /login route, receiving an authentication cookie in return. And secondly, a redirect to the / route using this cookie, or at least this is how I understand it.
This works fine in browsers, and in Postman, but it fails using the node.js app, for which I tried most of the popular http libraries (axios, follow-redirects, and built-in https).
The reason which I think it fails, is that the app does both requests together, without sending the auth cookie in the GET / request.
So my question is, how to force the app to use to returned cookie in the redirected request?
Below is a snippet of one of my trials using Axios:
axios({
method: 'post',
url: 'www.example.com/login',
withCredentials: true,
crossdomain: true,
data: loginCreds,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Cache-Control": "no-cache",
"Content-Length": Buffer.byteLength(loginCreds),
"Host": 'www.example.com'
}
}).then(res => {
console.log(res);
});
}).catch(err => {
console.log(err);
});
Using the sample Python code provided by the Bureau of Labor Statistics I was able to successfully access their API and print the JSON containing the data series in the console. Python code below:
#BLS query.
headers = {'Content-type': 'application/json'}
data = json.dumps({"seriesid": ['CES0000000001'],"startyear":"2010", "endyear":"2019"})
result = requests.post('https://api.bls.gov/publicAPI/v2/timeseries/data/', data=data, headers=headers)
print(result.text)
While the Python code works just fine, I would prefer to use JS, but have been unsuccessful in doing so. I have tried using fetch, but I am not making any progress. See JS code below:
fetch('https://api.bls.gov/publicAPI/v2/timeseries/data/', {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({seriesid: ['CES0000000001'], startyear:"2010", endyear:"2019"})
})
.then(function(response) {response.json()})
.then(function(json) {console.log(json)});
I am sure I am messing up something simple here, but I'm at a loss. Any help would be greatly appreciated. For reference, additional info from the BLS on their API can be found at this link:
https://www.bls.gov/developers/api_signature_v2.htm
Try using this,
const data = { username: 'example' };
fetch('https://api.bls.gov/publicAPI/v2/timeseries/data', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
But what I think the real problem might be that you are using an API which has authentication used, so make sure that you are using the api key along with the post req itself.
if you can have the api documentation, please refer it and see how to make a authenticated request to the server.
If you want to use regular JavaScript's fetch in Node.js, it won’t work, One reason for that is because, NodeJs doesn't make requests via the browser, but Fetch API was made to make requests via the browser
You’d have to use a package called node-fetch, it's just like the regular fetch, but for NodeJs.
You can get it here -> https://www.npmjs.com/package/node-fetch
or you can also use the standard NodeJS HTTP package.
or packages like axios or request to make HTTP requests in NodeJS
I use fetch() to send a post request for logon,
after server validation, I use req.session.account = account[0]; to save the account information to the session and return a redirect URL,
But after the redirect, the account information in the session is lost, why is that?
If you would have some example code, that would help us track down the problem. My first idea would be to make sure express-session is properly configured:
var app = express();
var session = require('express-session');
app.use(session({
secret: 'ibfiyegfiyegfe' // Secret is a required option.
}));
For futher configuration options, see the express-session repository.
EDIT: Based on the additional information, I'm guessing you have express-session configured to also use cookies for managing the sessions. What this means, is that for every HTTP request Express sends a response back that includes a cookie. jQuery based AJAX calls will ignore the response cookie however, which causes consecutive requests to Express to look as if you never logged in. To allow saving the cookie when performing AJAX requests with jQuery, use the xhrFields field to enable withCredentials:
$.ajax({
url: "http://....",
type: "POST",
xhrFields: {
withCredentials: true
},
data: {username: username, password: password},
success: function(responseBody) {
console.log("success!");
},
error: function(responseBody) {
console.log("error!");
}
});
Hope this helps.
Sorry to everyone, I don't making the question clear.
I use the fetch() method send a request to logon.
fetch('/logon', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
account: account,
password: password
})
}).then(function(response){
return response.json();
}).then(function(json){
if(json.success == 1){
window.location.href = json.redirecturl;
}else{
indexDispatcher.dispatch({
actionType: 'logonFaild',
errorInfo: json.msg
});
}
});
And the server's response is just simple JSON:
if (err) {
consoloe.log(err);
} else {
req.session.account = account[0]; //save account to session
var redirecturl = '/team/' + team[0].id;
console.log("account添加到session了");
res.json({
success: 1,
redirecturl: redirecturl
});
}
But when the client get the redirecturl and redirect, the account data is lost,so it will occur a TypeError: Cannot read property 'id' of undefined(id is saved in req.session.account).
But when I use jquery $.ajax relpace fetch, it works well. I don't know the reason.
I had the same experience like you hundreds of times which I finally found the problem. You don't need to worry if cookies enable or disable.
You just have to re-declare parts of your scripts (variables-the data which you want to display) in a if else condition.
Just redeclare the same thing using !isset and then else with the same variables mentioned twice in the if else condition, if you understand what i mean.
It will call back the same variables over and over. And make sure start session is above the page. no need to worry about headers or white lines, it has actually nothing to do with it.
I've tried it a million times. You don't need to bother using ajax etc. PHP can do almost everything. cheerio.