Authenticate via POST request in Node.js - node.js

I'm trying to authenticate with a site through node by sending my username and password through a POST request, as that's how the login form seems to be doing it. When trying it out with Postman it works just fine and I'm redirected to the my dashboard.
Username and password fields are unfortunately not labeled as username and password, but as j_username and j_password.
This is the data Postman shows me (for reference):
POST /path/for/auth/request HTTP/1.1
Host: site.com
Cache-Control: no-cache
Postman-Token: b6656210-caeb-2b62-d6b6-e10e642b200b
Content-Type: application/x-www-form-urlencoded
j_username=myusername&j_password=mypassword
So I try this in node:
var request = require('request');
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: 'https://site.com/path/for/auth/request',
body: "j_username=myusername&j_password=mypassword"
}, function(err, res, body){
console.log(body);
});
But unfortunately it's coming back empty and err is set to null.
What could be going wrong here? Or is there a better way of authenticating with this resource? As far as I can tell Basic Auth through a header isn't possible here.
Thanks.

The site is probably sending you an HTTP 302 redirect, so that's considered success, which is why there's no error, but there's also no response body, which is why it's "empty". You'll want to look at the statusCode as well as the Location header in the response.

Related

500 error depending on data submitted in POST request

Setup: NodeJS / Express / Helmet API running on Azure App Service, CORS set to allow * so should be all fine.
Client web setup running locally on NodeJS (http://localhost:3000)
I'm trying to POST some JSON from the web client to the API for login validating purposes. Works for some requests and not others, seemingly depending on what actual values I am posting.
I've got a bit of code that uses the Fetch API to send login details and validate them, as follows:
const response = await fetch(`${baseUrl}/auth/validate`, {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({EmailAddress: email, Password: password}),
}).catch(error => {
alert('Unable to check login');
});
If the value of email and password are both just me leaning on the keyboard, say 'skdjflsjdf' then it's all fine - the server gets my POST, validates that the login is rubbish and bounces back my error. It allows it because I get the Access-Control-Allow-Origin: * header back, so Chrome is happy.
If the value of email is an actual email address, I don't get the Access-Control-Allow-Origin: * header back and Chrome gets very upset of course.
I can't even begin to imagine how I've gone wrong here and I certainly don't seem to be able to find the right phrase to Google for a sensible answer. I'd really appreciate any help... Thanks.

AWS API Gateway returns access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response

This may seem like it's been asked a million times but I've tried adding to both my frontend (React) and backend (Lambda with Node.js):
Access-Control-Allow-Headers
Access-Control-Request-Headers
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE,PATCH,OPTIONS'
But I still get this error:
Access to XMLHttpRequest at 'https://<API-INVOKE-URL>/prod/notes' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Here's my Lambda code to handle response:
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};
Here's my React code to send the POST request:
createNote(note) {
return API.post("notes", "/notes", {
headers: {
"Authorization": this.state.token,
"Access-Control-Allow-Origin": "*"
},
body: {
userid: this.state.username,
noteid: 'new',
content: 'from frontend'
}
});
I've tested my Lambda function from the console and it works (able to do CRUD to DynamoDB).
I've turned on CORS for my API Gateway resources and deployed the API.
I've tried using PostMan with:
Headers:Content/Type: application/json
Authorization: <MY_TOKEN>
*With and without* Access-Control-Allow-Origin: *
and it works: the request is sent successfully from PostMan to API Gateway results in a new item in my DynamoDB.
Actually adding some data in header converts POST request to OPTIONS.
So that, it will fire to requests:
1) with OPTIONS method
2) After getting a successfull response for OPTIONS request, the actual API call will occur.
To handle CORS you should use this in the backend.
Just to throw some light to the problem. Some browsers will do a "preflight" check to your endpoint. That means that will invoke your endpoint with OPTIONS method before making the POST method call you expect. In AWS, go to API Gateway and create a new resource , check the option to Create Options, that will create the default response headers that you need to add to your endpoint.
CORS requires a direct connection between the client and server. Your browser may be blocking the connection for security reasons.
HTTP versus HTTPS
I'd also try enabling downloads on your browser.
I believe you should also add the bearer to your token in the authorization header like:
'Bearer TOKEN_VALUE'
Thank you, guys. I've upvoted your answers/suggestions. I'm sure they're helpful in most cases. I've figured out why I had that error.
My bad: I have both resources like this:
/notes/ (method: any)
/notes/{noteid} (method: any)
and the Invoke URL is literally <path>/notes/{noteid} (with the {} included in the string) in AWS API Gateway. I was assuming it'd be something like /notes/:noteid
So the frontend code should be like this:
return API.post("notes", "/notes/{noteid}", {...}

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I am using nodejs server, express framework and fetch library to send request to another server which is in different domain. For one of my endpoint consider (localhost:8080/login) i am rendering ejs file when the user clicks login button i am sending a fetch request to an api (https:otherserver.com/login) different server which is in other domain. i am not able to send this request. I am getting this error :
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 404. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I am not sure how to handle this issue. please suggest some ideas or links which can solve this issue.
You can use cors middleware on your server.
Simplest way to use it is to add :
app.use(cors())
before all of your route handlers.
I found the solution for my problem. I am trying to explain what i understood as i am a beginner in server side and web development.
This was the problem i faced :
For one of my endpoint in my nodejs server, consider (localhost:8080/login) i am rendering ejs file when the user clicks login button in that ejs file, i am sending a fetch request to an api (https:otherserver.com/signin) of different server which is in other domain. i am not able to send this request. I was getting cors problem.
Cors problem was occuring because the server domain(my nodejs server) which rendered the ejs file and the other domain(https:otherserver.com/signin) to which i was making fetch request after clicking login button was different.
so solution was :
I need to make the fetch request first to the same domain(my nodejs server localhost:8080/api/signin). And then from this server i should call the api of other domain(https:otherserver.com/signin). By doing this we wont get any cors issue. Because the client side ejs file is requesting to the same server which has rendered the file. And then the server is bypassing the request to the other server.
code from client side javascript file. /api/signin is an endpoint in my local nodejs server and u can add the options:
options ={
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
body : JSON.stringify({
email_address : emailId,
password : pwd
})
};
fetch("/api/signin",options)
.then(function(res) {
console.log(res);
}).catch(function(error) {
console.log(error);
});
code from local nodejs server side:
express.use('/api/', function (req, res, next) {
var options = {
method : req.method,
headers :req.headers,
body : JSON.stringify(req.body)
};
fetch('https://otherserver.com'+req.path,options)
.then(response => {
return response.json();
}, error => { console.error(error)})
.then(function(json){
res.send(json);
})
.catch(function(error) {
res.send(error);
});
})
Hope this may help someone who is beginner in server development.

"Fetch failed loading" - fetch works in Postman but fails in Chrome & Safari

Update: Fixed. It looks like the request was coming back as a 503 (as it should), then my app refreshed and displayed the non-error message: "Fetch failed loading". I just wasn't seeing the response because of the refresh.
I am not able to make a fetch request from my locally-hosted Create-React-App to my Heroku-hosted Node server.
My Node server has CORS enabled. If I make a POST request via Postman, I get an appropriate response (503, because currently there is no database hooked up, so the data is not being saved. If I should be sending back a different response, let me know). My Postman request has 'application/json' as the content-type, no authorization, and a body of { "rating": "5", "zipcode": "0" }.
However, when I make a POST request from my React app, I get a message in my console: "Fetch failed loading: OPTIONS "https://shielded-gorge-69158.herokuapp.com/feedback"." There is no associated error, only the message. There is no information about the request in my Network panel.
The fetch request works when I do it locally, from localhost:3000 (my app) to localhost:5000 (my server). It only fails when I try to make the request to the (otherwise identical) server hosted on Heroku.
This is what the fetch request looks like:
return fetch('https://shielded-gorge-69158.herokuapp.com/feedback', {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({ rating: userRating, zipcode: userZip })
}).then(res => {
if (!res.ok) {
throw new Error('Error:', res.statusText);
}
return res;
}).catch(err => console.error(err));
Edit: I'm continuing to research and it seems like Postman shouldn't/doesn't make preflight requests (https://github.com/postmanlabs/postman-app-support/issues/2845). So perhaps that is the issue — but why would the request be working when my server is local, but not when it is hosted on Heroku?
use 'Content-Type' instead of 'Content-type'.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests
https://fetch.spec.whatwg.org/#cors-safelisted-request-header
Explanation: when you use incorrect case then it is considered as a custom header and hence, a preflight request is sent in such cases. Now if OPTIONS request is implemented on server with correct cors spec then next POST will be sent, else it wont be sent and request will fail. More on this in above links.

nodejs- unable to fetch form data

I'm using Express JS (v 4.15.3) for building a node api.
I'm trying to fetch the values send from a form (via POSTman client). I'm not able to fetch it.
This is my form
with headers specified
Without headers
This is how I'm trying to fetch it:
router.post('/login',function(req, res, next) {
var email= req.body.email;
//var email= req.query.email; //also tried this
res.json({
value: email
});
});
I'm not getting error.
Note: I have included body parser.
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
Can anyone tell me why I am not getting the value? Thanks!
This is my first attempt at learning Node JS.
Your code seems perfectly alright. Though the issue is with the way you are sending request from POSTman client.
When you are sending request using use form data, POSTman sends this request as multipart/form-data, which actually sends your data in the format as below:
POST /api/login HTTP/1.1
Host: localhost:3000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="email"
example#example.com
----WebKitFormBoundaryE19zNvXGzXaLvS5C
For multipart/form-data requests you need to use multer middleware, if you really need file-uploads with your application. But for your case you can just send data without using use form data (un-check the use form data checkbox), and setting content-type header as:
Content-Type: application/x-www-form-urlencoded
So after all these modifications your raw web request should look something like below:
POST /api/login HTTP/1.1
Host: localhost:3000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
email=example#example.com
The POSTman screen capture for building the request and response is as below:
The POSTman screen capture for Raw request and response is as below:
Hope this will help you.
Try to set Content-Type to application/json and in body in raw write in json format like this :
{
"email":"example#gmail.com"
}
Here are the images which you can refer.
Don't forget to upvote the answer if you find it helpful.

Resources