I'm trying to send a token from the client to fetch that on my node.js server.
then I want the response of the server to set this token in the header so that each further request from the client will send along with the token.
I'm using vanilla javascript for the front end and express on my backend
here's the fetch request:
data = {
id: idToken
};
fetch("http://localhost:5000/check", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).then(response => {
console.log(response);
});
this is the server code:
app.post("/check", (req, res) => {
console.log(req.body.id);
res.setHeader("token", req.body.id);
res.redirect("/");
});
where am I wrong?
Headers are a generic way to send metadata with an HTTP message. They aren't a generic way to persist session data.
The tool designed to do what you want is a cookie.
Use res.cookie() to set a cookie and the cookie-parser middleware to read it back.
Consider using cookie based sessions instead.
Related
I have a server where I send a jwt cookie to the user's browser after login and I put the setting of "httpOnly: true" to ensure against XSS.
Now I want to send a request to the server from the client side how do I send the jwt to the server if I can't access it on the client side?
(I'm using axios and Java Script)
This is how I would do it if "httpOnly: true" was not set.
But because it is set then the jwt is undefined:
const jwt = Cookies.get('jwt')
axios.get('/Any address', {
headers: {
Authorization: `Bearer ${jwt}`,
},
withCredentials: true,
}).then(function (response) {
console.log(response)
}).catch(function (error) {
console.log(error)
})
If the cookie is set, then the web browser would anyway send it in the header, right?
Is that not happening? If not, please check if the cookie(s) are set properly and verify it on the client, whichever client you are using
here is my problem, when I post from using the classic form post the
post goes to server if certain conditions are met the server then redirect to the specific page
but when I use fetch request for posting due to the need to model data a certain way a yet with similar request the server doesn't redirect me to the wanted page and it just stays where it is , any solution my bet is I need to add something to my fetch so the fetch will respond to the redirection sent by the server.
// Front-End Code Fetch
fetch('/pin', {
credentials: "same-origin",
mode: "same-origin",
method: 'post',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(inputJSON)
})
// Back-End Code
exports.pin = async (req, res, next) => {
res.redirect(`/app`)
}
// Routing model
app.route('/pin')
.post(authentication.pin)
app.route('/app')
.get(toAppControler.getApp)
See this answer: you can't redirect a POST to a GET.
Can you add this to your code? This way you can either GET or POST /app?
app.route('/app').post(...)
I have a react app on an express server. I'm making a GET request to the server from the client using fetch and the response is coming back as Content-Type text/html when I'm on chrome but application/json when I try in Postman. I want it as JSON.
Postman Response:
Network Tab in chrome when called from a button:
I've tried changing the content type in the express request.
app.get('/spotify/search-track', (req,res) => {
spotify.searchTrack(req.query.name).then(function(result)
{
res.setHeader("Content-Type", "application/json");
res.send(result);
});
});
React GET request:
fetch('/api/spotify/search-tracks?name=' + val,
{
method: "GET",
data: null,
headers : { "Accept": "application/json" }
}).then(response => response.json()).then(data => console.log(data));
I'm also getting this error on Chrome - probably because the < is from the HTML.
Instead of
res.send(result)
You can use
res.status(200).json(result)
I didn't realize that the request is calling /api/spotify/search-tracks and the server is expecting /search-track. My bad there ;)
I have a MERN + Passport.js application that is using fetch to make a call to my express API in order to retrieve data stored in a cookie. I have my React frontend routed to localhost:3000, and my backend routed to localhost:3001. My cookies are not being saved, and thus my session is not persisting within my browser. It is not an issue with the express-sessions or passport middleware, as when I use POSTMAN to execute the necessary calls to my API, the cookie is stored and the session persists.
It is only when I attempt to pass this information through/to my front end that things go wrong. I have been stumped for a while and can't seem to find an answer anywhere.
This is the line that I am using to save the cookie:
handleLogin(event) {
event.preventDefault();
fetch("http://localhost:3001/users/login", {
// credentials: 'include',
credentials: 'same-origin',
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password
})
})
// .then( (response) => response.json())
.then( (response )=> {
if(response.message){
alert(response.message);
}
})
Which correctly calls my API, which logs the current session, user data, and cookie.
Upon refreshing and making another request, I lose the cookie (it was never properly stored in the first place I think), and all session data.
This is the get request that I make whenever I navigate to a new page:
componentDidMount(){
var current_user = "";
fetch("http://localhost:3001/users/", {
// credentials: 'include',
credentials: 'same-origin',
method: "get",
headers: {
'Accept':'application/json',
'Content-Type': 'application/json'
}
})
// .then( (response)=> response.json())
.then( (response)=> {
if(response.user){
current_user = response.user;
this.setState({
user: current_user
}), ()=> console.log(response);
}
})
}
In response, I get an undefined user and no other response, and the cookie is never stored in my browser. But again, if I do this in POSTMAN, strictly doing the POST request followed by that GET request, the proper user data is returned and the cookie is shown in POSTMAN as well.
Any idea as to why fetch is not passing the cookie information back to my front end? I have tried both credentials: 'include' and credentials: same-origin.
Thank you!
It seems like the problem, or at least part of it, is your use of same-origin. From Mozilla docs (italics my own):
omit: Never send cookies.
same-origin: Send user credentials (cookies, basic http auth, etc..) if the URL is on the same origin as the calling script. This is the default value.
include: Always send user credentials (cookies, basic http auth, etc..), even for cross-origin calls.
The definition of "same origin" does not include different ports.
If you change same-origin to include, fetch should start managing your cookies correctly.
If not - do you know for sure that the cookie is "never stored in the browser"? With Chrome, you can check chrome://settings/siteData.
I have been using DialogFlow v1 before using simply jquery and it was pretty straigh forward working!
Now that I have to switch to V2 I am stuck on how to keep somehow same code but just modify with the V2!
I have been looking at this client library for V2:
https://github.com/dialogflow/dialogflow-nodejs-client-v2#using-the-client-library
But I dont wanna use Node.js I just dont want to do somthing like node server.js to run the app, also I am not sure if I can mix jQuery with Node.js.
My previous code v1 looked like this:
fetch(url, {
body: JSON.stringify(data),
// cache: 'no-cache',
// credentials: 'same-origin',
headers: {
'content-type': 'application/json',
"Authorization": "Bearer " + configs.accessToken,
},
method: 'POST',
mode: 'cors',
redirect: 'follow',
referrer: 'no-referrer',
})
.then(response => response.json()) // parses response to JSON
Well I swtiched to ES6 for making http request for dialogflow but I would want the same code to use for V2, is this possible? Also I can no longer see access token for v2, how are we suppose to handle the auth for http calls?
I am really confused with the new V2 and since we switched to Enterprise Edition Account it is a must for us to use v2 and it kinda sucks!
Edit:
I am checking this example from documentation:
POST https://dialogflow.googleapis.com/v2beta1/projects/project-name/agent/intents
Headers:
Authorization: Bearer $(gcloud auth print-access-token)
Content-Type: application/json
POST body:
{
'displayName': 'StartStopwatch',
'priority': 500000,
'mlEnabled': true,
'trainingPhrases': [
{
'type': 'EXAMPLE',
'parts': [
{
'text': 'start stopwatch'
}
]
}
],
'action': 'start',
'messages': [
{
'text': {
'text': [
'Stopwatch started'
]
}
}
],
}
But I am somehow confused on this part: Authorization: Bearer $(gcloud auth print-access-token) where do I get access-token?
I have already done this part: gcloud auth activate-service-account --key-file= which I have no idea what is it doing after activating! I was hoping I would get back some access-token from this, but there seem to be nothing just a message that says Activated Service...
To use Dialogflow V2 API with browser AJAX just like V1, there is no simple way, unless you have the access token. I've run into same issue and figured out it can't be done without using their client libraries (SDK) or "google-oauth-jwt". In my example i used nodejs - google-oauth-jwt package which provides "access token" for my application which was used for browser AJAX calls. You don't have to use their nodejs SDK library, in case, you're handling logic on client side.
Setup Instructions:
1.Configure V2 API from V1 on the dialogflow account, follow the migration guide. Download the JSON file which has a unique email and key values. You might want to grant access to your application by registering the domains.
2.Create a nodejs application and use "google-oauth-jwt" to get the access token. Also, make this as a service to call it before hand to have the access token ready before making any ajax calls. Here is sample code:
app.get("/your_sample_web_service_to_get_access_token", (req, res, next) => {
new Promise((resolve) => {
tokens.get({
//find this email value from the downloaded json
email: 'xxx#xxx.iam.gserviceaccount.com',
//find this key value from the downloaded json
key: '-----BEGIN PRIVATE KEY-----xxx',
//specify the scopes you wish to access: as mentioned in dialogflow documentation
scopes: ['https://www.googleapis.com/auth/cloud-platform']
},
(err, token) => {
//rest api response
res.json({
"access_token": token
});
resolve(token);
}
);
});
});
3.From your client JavaScript, make an AJAX call using the access token you get from above nodejs application. Here is the sample code:
app.service('chatbot', function ($http, $rootScope) {
this.callAPI = function (user_entered_query) {
//I used detectintent REST API endpoint: find the project name from your account.
var endpoint = "https://dialogflow.googleapis.com/v2/projects/xxx/agent/sessions/123456789:detectIntent";
var data = JSON.stringify({queryParams:{}, query_input:{text:{text:user_entered_query,language_code:"en-US"}},outputAudioConfig:{},inputAudio:""});
var headers = {
//use the token from nodejs service
"Authorization": "Bearer " +$rootScope.token
};
return $http.post(_url, _data, {"headers": headers});
}
});