better way to intercept requests that nodejs further make - node.js

I have created a nodejs server A with the express framework. I have used request-promise module to make http requests to different server B. Browser makes call to server A with cookie data. This cookie contains the jwt token that I further want to pass to server B.
#Get("/users")
getUsers( #Cookie('token') token: any): any {
let usersPromise = Users.getUsers(jwt);
return Promise.all([usersPromise])
.then(response => {
return response.users;
});
}
I have created a Users class that further call server B using the request-promise module. One way is to pass the jwt token directly to every calls like this as I did in
let usersPromise = Users.getUsers(jwt);
is there any other way some intercept way to do this?

I have superagent package to intercept my all the request and appended the jwt to header.
TO configure this
Install superagent and superagent-use modules
npm install superagent superagent-use --save
Require the modules
var request = require('superagent-use')(require('superagent'));
Then define the superagent middleware
// interceptor used by superagent to add jwt in header for each request
request.use((req) => {
req.header.jwt = jwt;
return req;
});
and then to make calls
request
.get(url)
.query({ view: 'jsonView' });
Superagent is more useful than the request-promise as this module provide the promise and rxjs base apis , url prefix and an elegant way to append querystring.

Related

How do I access Express.js Cookie in React app?

I'm creating E-shop with MERN Stack
This is my response from the server on Login where you can see, the cookie is SET and it's sent from the Backend.
That means no there shoudln't be problem with BE, but the FE I will need to handle the Cookie on the FE.
How do I access this sent Cookie from Express in the React ?
I have tried something like this:
const handleLogin = async (event) => {
event.preventDefault();
try {
const url = "http://localhost:5000/api/auth/login";
const data = await axios.post(url, formFields);
const { user } = data.data;
// Here I have tried to access it from Headers where I can see it in the attached
// picture under Set-Cooki. But inside headers I can only see
// Content-Length and Content-Type
console.log(data.headers);
// Aswell I have tried react-cookie but docs are not clear enough for me.
// and this just sets cookie from react, I would like to use cookie from express
// and set it like this
// await setCookie("user", "INSERT_HERE_COOKIE_FROM_EXPRESS.JS", {
// path: "/",
// });
setCurrentUser(user);
await resetFormFields();
} catch (error) {
const data = error.response.data;
!data.error
? alert(`${data.message}`)
: alert(`${data.message}: ${data.error}`);
}
};
Thank you for any answers, I'm sure it's not that hard as I think and it's few lines of code.
As I see on your screenshot - you use express with httpOnly cookies:
https://developer.mozilla.org/ru/docs/Web/HTTP/Cookies -
A cookie with the HttpOnly attribute is inaccessible to the JavaScript Document.cookie API; it's only sent to the server. For example, cookies that persist in server-side sessions don't need to be available to JavaScript and should have the HttpOnly attribute. This precaution helps mitigate cross-site scripting (XSS) attacks.
And I think you don't want to use nonsecure cookies in your E-shop - so you can't access it, but you can use custom headers, so on your frontend it will be like:
fetch('/myapi').then(response => console.log(response.headers.get('myCustomHeader')));

get access token from back and cache it to browser

hey guys. i'm working with axios,nodeJS and vue . i want
to generate an accessToken in node (it's done) and get it
with axios (it's done too) and cache it to browser cache with
vue(don't know how), so whenever i want to send a request to
node,i could send it with headers of axios , i dont know if it's
possible or not ? need some help around here.
Yes, that's possible and is pretty common.
To do it, you just have to store the token in the browser memory (usually in the localStorage) and then use axios interceptors on the requests to automatically add the token.
How you can add items to local storage?
localStorage.setItem('my-key',my-value)
you can find the complete docs here.
axios.interceptors.request.use(
config => {
//here retrieve the token and add it (if present)
//most probably you would use VUEX for storing it
//in you app
const token = yourLocalStorageAccessor.getAccessToken();
if (token) {
config.headers['Authorization'] = 'Bearer ' + token;
}
// config.headers['Content-Type'] = 'application/json';
return config;
},
error => {
Promise.reject(error)
});
You can read about axios interceptors here.

How to make both req.files and req.body available in nodejs when the api is sent with axios

I'm using Axios npm package in my Node.js application which is a built-in microservices architecture. API-gateway is using Axios to call other services.
According to axios documentation, for POST method, request format is like: axios#post(url[, data[, config]]) . means only one argument data.
Can anyone tell me how I can send req.body & req.files data separately to Axios?
According to answer in Axios community to familiar question this could be achieved with the npm package form-data, which simulates WebAPI FormData on the node side.
This would allow you to send files and form fields to the API and receive it in form of multipart form data.
const axios = require('axios');
const FormData = require('form-data');
const form = new FormData();
// Second argument can take Buffer or Stream (lazily read during the request) too.
// Third argument is filename if you want to simulate a file upload. Otherwise omit.
form.append('field', 'a,b,c', 'blah.csv');
axios.post('http://example.org/endpoint', form, {
headers: form.getHeaders(),
})
.then(result => {
// Handle result…
console.log(result.data);
});
Bundle your data up as an object, and pass that object through to the axios request as a single payload.
On the other side of the API, you can access the object, and do as you wish.
var payload = { property1: 'values', property2: 'values2' }
now you pass payload around

Using cookies with axios and Vue

I have created a Node.js express server that connects to Salesforce.com using the SOAP interface provided by 'jsforce'. It uses session cookies for authorization via the 'express-session' package. So far, it has a POST method for login and a GET to perform a simple query. Testing with Postman has proven that this server is working as expected.
As the browser interface to this server, I have wrttien a Vue application that uses axios to perform the GET and POST. I need to save the session cookie created during login POST then attach attach the cookie to subsequent CRUD operations.
I have tried various methods to handle the cookies. One method I have tried is using axios response interceptors on the POST
axios.interceptors.response.use(response => {
update.update_from_cookies();
return response;
});
The function 'update_from_cookies' attempts to get the cookie named 'js-force' but it does not find it although I know it is being sent
import Cookie from 'js-cookie';
import store from './store';
export function update_from_cookies() {
let logged_in = Cookie.get('js-force');
console.log('cookie ' + logged_in);
if (logged_in && JSON.parse(logged_in)) {
store.commit('logged_in', true);
} else {
store.commit('logged_in', false);
}
}
I have also seen various recommendations to add parameters to the axios calls but these also do not work.
I would appreciate some advice about how to handle cookies using axios or some similar package that works with Vue
Thanks
The problem has been resolved. I was using the wrong syntax for the axios call
The correct syntax has the {withCredentials: true} as the last parameter
this.axios.post(uri, this.sfdata, {withCredentials: true})
.then( () => {
this.$router.push( {name : 'home' });
})
.catch( () => {
});

How can you use cookies with superagent?

I'm doing cookie session management with express with something like this:
req.session.authentication = auth;
And I verify the authenticated urls with something like
if(!req.session.authentication){res.send(401);}
Now I'm building tests for the URLs with mocha, superagent and should, however I can't seem to find a way to get/set the cookie with superagent. I even tried to request the login before the authenticated test but it is not working,
I have tried adding the request to the login in the before statement for the mocha BDD suite, however it is still telling me that the request is unauthorized, I have tested the authentication doing the requests from the browser, however it is not working from the suite any ideas why?
Use superagent.agent() (instead of plain old superagent) to make requests have persistent cookies. See 'Saving cookies' in the superagent docs, or the code examples: agency.js, controller.test.js.
Seems like following code works fine;
req.set('Cookie', "cookieName1=cookieValue1;cookieName2=cookieValue2");
If the issue is in sending cookies for CORS requests use .withCredentials() method
described here
request
.get('http://localhost:4001/')
.withCredentials()
.end(function(err, res) { })
Since you mentioned you need to both get and set the cookie:
Get:
const request = await Superagent.get('...')
const cookie = request.header['set-cookie']
Set:
Superagent.post('...').set('Cookie', 'cookie_info')
2020 +
A clean way to do it is:
create a simple cookie store
abstract set Cookie to send it in each request
update the cookie only when needed
Note I keep the same URL because I use graphql but you can make it a parameter:
const graph = agent =>
agent.post('/graph')
.set('cookie', cookieStore.get());
const handleCookie = res =>
cookieStore.set(res.headers['set-cookie'][0]);
let currentCookie="";
const cookieStore = {
set: cookie=>{currentCookie=cookie},
get: cookie=>currentCookie,
};
module.exports = {graph,connectTestUser,handleCookieResponse};
You can now just use graph(agent) to send a request and handleCookie(response) when you have a response that may update your cookie (set or clear), example:
graph(agent).end((err,res) => {
if (err) return done(err);
res.statusCode.should.equal(200);
handleCookie(res);
return done();
});
Add a cookie to agent cookiejar:
const request = require('superagent');
const {Cookie} = require('cookiejar')
const agent = request.agent()
agent.jar.setCookie(new Cookie("foo=bar"))

Resources