Responding with data to a Slack url in Express - angularjs

I have the following route in my Node backend with express middleware. My app uses the Slack backslash api to post a link to a user's channel. When user clicks it opens a form on an angular app hosted on heroku.
What I am looking to do is update the Slack user when the form get submitted.
So the question, how can I send a post request to slack url when the route below gets triggered(obviously the res is pointing to the /update). I've researched quite a bit and tried rewriting headers and using low level http methods, but I have a feeling there is a better solution to this. Many thanks for your help.
app.post("/update", function(req,res,next) {
res url -> http://slackapi/12345/
res.json({"text":"hello":}
})

res is not supposed to be sent to slack, this is the response to whoever contacted you. you need to send a different request to slack, and return whatever you want with res.
You can use request module to generate a http request to slack.
var request = require('request');
app.post("/update", function(req,res,next) {
request('http://slackapi/12345/', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
res.json({"text":"some answer to the requester"});
} else {
res.json({"text":"notify requester sending to slack falied"});
}
});
});

Related

Can a POST request be redirected as another GET request

I am working on a react application, where there is a need to send the object parameters inside a body because of confidentiality. So I am making a POST request from the react app client-side to the backend server like this
axios
.post('htps://java.backend.xyz/path1', {
data: password,
})
.catch(function (error) {
handle(error);
});
After making this POST request there is a preflight request with "method = OPTIONS" and "URL= 'htps://java.backend.xyz/path1'"...to which java-backend-server responds with status_code=200.
After the above preflight request, java-backend-server addresses the POST request and instead of sending a response the java-backend-server respond with a GET request (i.e redirect) as for example:
https://express-app.xyz/path2?query_para1=abc&query_param2=123, requestMethod=GET
And in response to the above GET request, the express app responds with status_code=200
But immediately after this GET request, there is a preflight request with request Method=OPTIONS and having the same URL as above i.e
https://express-app.xyz/path2?query_para1=abc&query_param2=123, requestMethod=OPTIONS
and for this above OPTIONS request express server responds with a status_code=204 which means that the client doesn't need to navigate away from its current page...this is something prohibiting my app to make a final redirect i.e after the backend server responds with a GET request, my react app is not able to make a redirect even search engine does not update the redirect URL which is
https://express-app.xyz/path2?query_para1=abc&query_param2=123
So, here Is this even possible? I am assuming that the preflight request after the GET request prohibits the client side to be able to make a final redirect. Can someone please help me with this scenario
I am not sure if I understand your problem correctly but what you can do is send a post response which will which will indicate client to redirect to specific location.
This can be achieved by sending response with status code 302 and location in header (location:redirect_url)
For more info :- https://en.m.wikipedia.org/wiki/HTTP_302

Unable to set cookies in Chrome using Flask-JWT-Extended, React, and Axios

Background and Issues
I have a Flask back-end running in localhost:5000 and a React SPA running on localhost:3000.
I was able to make them talk but when trying to store the token generated from Flask into Browser's cookies 1) response headers does not contain any cookies when doing console.log(response) after a successful POST from axios and 2) the cookies are not being set. But when inspecting the network > Login.js header, I could actually see the Set-Cookie key exists as response's header. I've tried multiple solutions from Google and StackOverflow but no solution seems to work here and I really can't figure out what is going on as the request is being made successfully, and Chrome is allowing third party software to set the cookies. And even I can see the tokens from Network > Login.js header.
Steps
1) Users enters in their username and password and hit login.
2) Axios POST call is made to Flask's back-end.
3) Process the data and generates a couple of tokens and set them into cookies.
4) Browser's cookie are set with few tokens. <- this part is not working.
Code
Flask back-end token generation using flask-jwt-extended
# app_config related to flask-jwt-extended
CORS_HEADERS = "Content-Type"
JWT_TOKEN_LOCATION = ["cookies"]
JWT_COOKIE_SECURE = False
JWT_COOKIE_CSRF_PROTECT = True
# post method from flask-restful for LoginAPI class
def post(self):
email = request.json.get("email")
password = request.json.get("password")
# some processing here.....
payload = {
"email": email
}
access_token = create_access_token(identity=payload)
refresh_token = create_refresh_token(identity=payload)
response = jsonify({"status": True})
set_access_cookies(response, access_token)
set_refresh_cookies(response, refresh_token)
return response
CORS using flask-cors
# in below code, I had some issues with putting wildcard (*) into origin, so I've specified to the React SPA's host and port.
CORS(authentication_blueprint, resources={r"/authentication/*": {"origins": "http://localhost:3000"}},
supports_credentials=True)
React SPA - making a post call using axios
# also tried `axios.defaults.withCredentials = true;` but same result.
export const login = (email, password, cookies) => {
return dispatch => {
const authData = {
email: email,
password: password
};
let url = 'http://127.0.0.1:5000/authentication/login/';
axios.post(url, authData, {withCredentials: true)
.then(
response => {
console.log(response)
})
.catch(err => {
console.log(err)
});
dispatch(authSuccess(email, password));
}
};
Below image is the response from successful post call in axios.
I'm not sure whether it is normal but response's headers are not showing any of the cookies that I'm setting from the back-end.
And below image is from Network > header for login/
As shown, you can clearly see the token information with Set-Cookie key. I've also checked that they aren't secure.
And finally when I check my cookie tab from application > cookies, I do not see anything.
So the issues were coming from the localhost.
I have a Flask back-end running in localhost:5000 and a React SPA running on localhost:3000.
From above statement, to be very specific, I was running the back-end on localhost:5000 and running the React SPA on 127.0.0.1:3000.
Once I've changed the 127.0.0.1 to localhost, it worked like a charm.
And a side note, after playing around with CORS, I think it will be a lot easier to use Nginx and proxy_pass to pass the request coming from React SPA to back-end to avoid using CORS completely, because if one have to use the CORS in different environment such as test, staging and etcs, one would have to set up the CORS at the web server level e.g) Nginx anyway and it requires slightly different configuration that how I set up for local environment anyway.

Trying to open new window with Authorization header (react) from application to connect user on our website

Context issue : We have an app using React and axios to do some requests from our API. We also have a website which is online and ok. I need to develop the "Account" part of the app but time and money are missing. Solution is to do a link in the app that redirect to the "Account" part of the website.
So I have to pass Authorization Header with the Bearer Token in my request, and then open this window with the token. But I really can't make this work. I tried with axios but I'm not really comfortable with it (not me who develop the whole app). So I try with the old XMLHttpRequest().
<a onClick={this.onRedirectAccount}>
onRedirectAccount = e => {
e.preventDefault();
var redirectAccountUrl = "urlToMyAccountOnWebsite";
const http = new XMLHttpRequest();
http.open("GET", redirectAccountUrl);
http.withCredentials = true;
http.setRequestHeader("Accept", "application/json, text/plain, */*");
http.setRequestHeader('authorization', 'Bearer '+ localStorage.getItem("token") );
http.send();
window.open(redirectAccountUrl);
If I do the request on Postman, I can see I am connected as user. I am also connected as user when I look at the preview of my request in the browser. But the window which is opening still tell me I'm not connected. I guess it's because my window.open doesn't keep the Authorization header on itself.
Have you got any ideas what I'm doing wrong, any clue to solve this ? Thank you and please feel free to ask for more details if needed.
You want to redirect user to urlToMyAccountOnWebsite. You can not set HTTP request headers unless you are making an async request.
A solution, send your token as a get parameter. Change your url which to be redirected like that:
yourSite.com/account?token=someTokenString then, handle and use it in the redirected page.

Make an API endpoint private

I'm developing a little webApp with AngularJS, express, nodejs and Passportjs. I have been creating endpoints on my API on demand but now I have a problem.
I have an endpoint which cannot be called by the users when they want. This API call is made when a user make an specific action in the app, so they earn points.
The endpoint is something like /api/users/updatePoints and I don't want the users with the developers tools resending the call and earning points they don't deserve.
How could I accomplish this? I have been thinking for a day but I can't think of anything reasonable.
Thank you in advance :)
--EDIT--
At last I have just deleted that ENDPOINT and write directly in the database in server-side. Not the solution I wanted but good enough. Thank you!!
It's already too late to answer but I think this could help someone.
To Privatize an endpoint, Allow only your whitelisted Origins by setting the respective response headers and for all other users send a 403 status code (Which implies forbidden, 401 says try again).
Here is an example of middleware that privatizes endpoints.
module.exports = function (allowedOrigins) {
const whitelistedOrigins = Array.isArray(allowedOrigins) ? allowedOrigins : [allowedOrigins];
return function (req, res, next) {
const origin = req.headers.origin;
if (whitelistedOrigins.indexOf(origin) > -1) {
res.setHeader("Access-Control-Allow-Origin", origin);
next();
} else {
res.status(403).json({
msg: "This is a private Endpoint, Please contact the Admin",
});
}
};
};
Here is an example of usage.
const privatizeEndpoint = require("../customMiddlewares/privatizeEndpoint");
router.post("/someEndpoint", privatizeEndpoint(["http://myprivate.domain.com"]), (req, res) => {
console.log("Inside Private Endpoint");
});
However, your endpoint will be still exposed but at least it will be served only to your whitelisted domains.
Notice that even requests without origin will be blocked (curl commands or through POSTMAN).

Request changed from POST to OPTIONS hangs

I am trying to send a POST request to an endpoint over HTTPS.
The request has 2 headers, content-type (application/json) and an apiKey.
I am using the request in a PhoneGap application built in Angular, and when the request is sent its method is changed to OPTIONS.
I know this is standard practice for browsers due to CORS, but I have a payload which I need the server to take, and I'm told by the server guys that OPTIONS requests have an empty payload with CORS (although I can't find verification on this).
The server is set up for CORS and should accept POST and OPTIONS.
For some reason my request hangs.
Angular code:
var submitDBIDResource = $resource(env.loginUserUrl, {}, {
save: {
method: 'POST',
headers: { 'apiKey': apiKey }
}
});
submitDBIDResource.save({"dbid": dbid}).$promise.then(function(data) {
console.log(data);
return data;
});
I have in my config.xml file
Any ideas what I need to do?
Thanks
The browser will automatically send an OPTIONS request before it sends the POST request. The OPTIONS request must respond with the appropriate response or else the browser will not send the POST request.
Your backend guys need to create two request handlers, one for the OPTIONS and one for the POST.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Resources