I'm new to Express JS and Node JS.
I intend to implement a Auth-Server in Express Middleware manually
I'm using https://github.com/ranm8/requestify to make the request
const requestify = require('requestify');
app.use(function (req, res, next) {
var config = require('./config-' + process.env.REACT_APP_ENV)
var redirect = config.ADMIN_UI_URL
// Perform login to Auth-Server
if (req.originalUrl.startsWith('/?code')) {
let auth_code = req.query.code
let params = {
'grant_type': 'authorization_code',
'code': auth_code,
'client_id': config.OAUTH_CLIENT_ID,
'redirect_uri': redirect
}
requestify.post(config.OAUTH_ID_URL+'/oauth2/token', params).then(function(response) {
console.log(response.getBody()); // There is not data post to the Auth-Server
});
return res.redirect('http://google.com');
}
// Check Token
if (req.cookies._token === undefined) {
let url = config.OAUTH_ID_URL + '/oauth2/authorize?' + 'response_type=code' + '&' + 'client_id=' + config.OAUTH_CLIENT_ID + '&' + 'redirect_uri=' + redirect
return res.redirect(url)
}
next()
})
I can check user token and recieve auth_code just fine. But I can not request a token out of logged-in user by making a post request to Auth-User
It seems like I miss understand how NodeJS, Epxress work, or some kind of the scope here
Please help me out! Thank you
Try to check what is the error you are getting. add error handler like this
requestify.post(config.OAUTH_ID_URL+'/oauth2/token', params).then(function(response) {
console.log(response.getBody()); // There is not data post to the Auth-Server
}).error(function(error){
console.log(error) // see if anything is coming in error object
});
My bad, I should use https://www.npmjs.com/package/request#forms package
request.post({url:config.OAUTH_ID_URL+'/oauth2/token', form: bodyData},
function(err,httpResponse,body){
console.log(err);
console.log(body);
})
It works now!!!
Thank you
Related
I am trying to work with JWT in a node.js application.
I followed this tutorial.
But I am facing problems at the level of the middleware:
function authenticateToken(req, res, next)
which is at the timing 10:30 in the video.
When I run the code I always have:
authHeader == null
I have tried various things to find other possible forms for req.headers['authorization'] like req.headers.authorization but to no avail.
I need to say that I have a route in my app that allows me to login and that I use right before using the route hitting the middleware. But in any case the authHeader keeps being null.
What should I do to make sure I get a valid authHeader as expected for the app to work as in the tutorial and move forward?
In case this may be useful, here is the complete code for the middleware function:
function authenticateToken(req, res, next) {
// Get the jwt access token from the request header.
const authHeader = req.headers['authorization']
const token = authHeader && authHeader.split(' ')[1]
if (token == null) {
console.log('authenticateToken-401')
return res.sendStatus(401)
}
jwt.verify(token, 'myBigSecret', (err, user) => {
console.log(err)
if (err) {
console.log('authenticateToken-403')
return res.sendStatus(403)
}
req.user = user
next()
})
}
And also the code that is run when a user logs in:
app.post('/login', async function(req, res) {
Parse.initialize(process.env.APP_ID);
Parse.serverURL = process.env.SERVER_URL;
Parse.User.logIn(req.body.usrname, req.body.password, {
success: user => {
// Let us handle this using JWT.
const jwtUser = {name: req.body.usrname}
const accessToken = jwt.sign(jwtUser, 'myBigSecret')
res.setHeader("Authorization", 'Bearer '+accessToken);
res.json({accessToken: accessToken})
},
error: (user, error) => {
console.log('Error: '+error);
res.render('pages/login.ejs', {});
},
});
});
You need to set headers in your request, looks like you didn't set headers in your request
On the login code above you have Signed using jwt so that it can be used when client app want to access some restrictable routes on your backend
Now whenever clients want to access route from frontend you need to set authorization token in ajax as header Something like this
$.ajax({
url: "/apiyouwanttoaccess",
method: "GET",
headers: { Authorization: "Bearer " + Cookies.get("token") }
})
The above ajax code should be somewhere around js code where you want to access secure routes.
You have already signed token on your login(2nd code snippet) so it can be used within specific user by setting the cookies
I'm making some requests from my express server, and I'm wondering how I can pass an error message to the client side. I want to be able to see the error message when I console log from the client as well as from the server, but I'm not sure how to relay this message back to the client to make that possible.
Here is an example of a request from my server.js file
app.get('/assign*', (request, response) => {
var baseurl = 'https://OURACC.nocrm.io/api/v2/'
var apikey = crmkey;
var pathname = request.url; // retrieves the requested pathname (ie, /crm/path)
pathname = pathname.split('?');
pathname = pathname[0].split('/')
var parameters = request.query.params;
var path = pathname[2]; // gets request path for the crm
var lead_id = parameters.lead_id
var user_id = parameters.user_id
var params = {
user_id: user_id
}
if(path === 'leads'){
axios.post(baseurl + path + '/' + lead_id + '/assign',
params
,{
headers: {'X-API-KEY': apikey, content_type: "json", accept: "application/json"}
}).then(function(res){
response.send(res.data);
}).catch(function(error){
console.log("ERROR in /assign/leads/{id}/assign" + error);
})
}
})
This is what the call to this request looks like client side
$.get('/assign/leads', {params: data}).then(response => {
console.log(response);
}).catch(error => {
console.log(error);
})
I've tried this server side
response.send(error)
but this doesn't return me anything client side like I was expecting.
I'm sure this is something simple, but I couldn't find much online about it, thanks.
If I read your code correctly, just put response.send(yourErrorMessage) in the catch block
You have to specify response code. For example:
res.status(400);
res.send('None shall pass');
I sent information from angular to a node.js file. I would like to know how can return information from the node.js to angular2.
Code in index.js
app.post('/', function(req,res){
var body = req.body;
*/ information received from angular2 file
(...)
*/ then return information back to angular2 file. **How to do this?**
};
Can someone help me please? Thank you.
First you should learn how is the flow of the http requests.
This is an example using $resource an Angular built-in tool.
The following is a representation of a search functionality where I am sending as a param what the user is looking for, from a search text box in the view:
// :search is the param
angular.module("MyApp")
.factory("Search", function($resource) {
return $resource("/api/search/:search", {}, {
query : {
method : "GET",
isArray : true
}
});
});
This is the controller:
All this controllers does is to watch if there is an user typing in the input text for search and taking the what the user is writing and sending it to the backend, working along with the factory/service which is above. This functionality sends the data to the backend in order to GET a query which is an array of the result of the searched.
angular.module('MyApp')
.controller('AddCtrl', function($scope, $alert, Show, Search) {
$scope.showName = '';
$scope.data = {};
$scope.addShowToModel = '';
$scope.$watch('showName', function (tmpStr) {
if (!tmpStr || tmpStr.length == 0) return 0;
if (tmpStr === $scope.showName) {
Search.query({ 'search': $scope.showName })
.$promise.then(function(data) {
$scope.responseData = data;
})
.catch(function(response) {
console.log(response.error);
});
}
});
});
And here the code from Nodejs:
app.get('/api/search/:search', function(req, res, next) {
var searchParam = req.params.search
.toLowerCase()
.replace(/ /g, '_')
.replace(/[^\w-]+/g, '');
var parser = xml2js.Parser(); // npm module to convert xml to json
request.get('http://thetvdb.com/api/GetSeries.php?seriesname=' + searchParam, function (error, response, body) {
if (error) return next(error);
parser.parseString(body, function (err, result) {
if (result.Data.Series !== undefined) {
// this is how you send the data to the frontend
return res.status(200).send(result.Data.Series);
} else {
res.status(411).send({message: searchParam + " wasn't found"});
}
});
});
});
So, to put it simpler:
app.post('/', function(req, res){
var body = req.body;
console.log(body);
return res.send(//whatever you need to send);
};
Sometimes you don't want to send data to the frontend but a status code to see how the operation went:
app.post('/', function(req, res){
if(everythingIsFine) {
// send only status code
res.sendStatus(200);
}else {
// in case you want to send status + message
res.status(401).send('Invalid whatever thing');
}
};
Hope it helps!
EDIT
In the service, you can use $http instead of $resource. That is the not the important thing on my answer but just telling you. According to a comment:
It would be more appropriate to use $http.get instead of $resource. $resource is intended for RESTful CRUD endpoints. A search endpoint does not fit that specification.
I have been having this issue. It seems like it works for a while and then breaks without much rhyme or reason to it.
router.get('/home/', function(req, res, next) {
var code = req.query.code;
console.log("acquired code from SC");
req.SC.authorize(code, function(err, accessToken) {
if ( err ) {
throw err;
} else {
console.log("traded code for access token");
req.session.oauth_token = accessToken;
// Client is now authorized and able to make API calls
//res.render('home', { token: accessToken });
soundcloud.getLoggedInUser(accessToken, function(user){
console.log("done getting user from SC");
});
}
});
});
Here is the getLoggedInUser function.
//get data for the user who is logged in
function getLoggedInUser(accessToken, done){
var href = 'https://api.soundcloud.com/me?oauth_token=' + accessToken;
getRequest(href, done);
}
//used for get requests to soundcloud API
function getRequest(href, done){
console.log(href);
requestify.get(href).then(function(response){
console.log(done);
done(response.getBody());
});
}
Here is the output.
acquired code from SC
traded code for access token
https://api.soundcloud.com/me?oauth_token=
[Function]
I'm guessing this is a problem with my node / express setup rather than a problem with this code itself. Any ideas?
I've come across many tutorials explaining how to scrape public websites that don't require authentication/login, using node.js.
Can somebody explain how to scrape sites that require login using node.js?
Use Mikeal's Request library, you need to enable cookies support like this:
var request = request.defaults({jar: true})
So you first should create a username on that site (manually) and pass the username and the password as params when making the POST request to that site. After that the server will respond with a cookie which Request will remember, so you will be able to access the pages that require you to be logged into that site.
Note: this approach doesn't work if something like reCaptcha is used on the login page.
I've been working with NodeJs Scrapers for more than 2 years now
I can tell you that the best choice when dealing with logins and authentication is to NOT use direct request
That is because you just waste time on building manual requests and it is way slower,
Instead, use a high lever browser that you control via an API like Puppeteer or NightmareJs
I have a good starter and in-depth guide on How to start scraping with Puppeteer, I'm sure it will help!
Or using superagent:
var superagent = require('superagent')
var agent = superagent.agent();
agent is then a persistent browser, which will handle getting and setting cookies, referers, etc. Just agent.get, agent.post() as normal.
You can scrape the data from sites that require authentication like csrf token.
Using the cookies for each request like this:
var j = request.jar(); // this is to set the jar of request for session and cookie persistence
request = request.defaults({ jar: j }); //here we are setting the default cookies of request
Here is small code to elaborate it further:
var express = require('express');
var bodyParser = require('body-parser');
var querystring = require('querystring');
var request = require('request'); //npm request package to send a get and post request to a url
const cheerio = require('cheerio'); //npm package used for scraping content from third party sites
var cookieParser = require('cookie-parser')
var http = require('http');
var app = express();
app.use(cookieParser());
var _csrf; //variable to store the _csrf value to be used later
app.use(bodyParser.json());
var html = '';
var j = request.jar(); // this is to set the jar of request for session and cookie persistence
request = request.defaults({ jar: j }); //here we are setting the default cookies of request
//___________________API CALL TO VERIFY THE GMS NUMBER_______________________
app.get('/check', function(req, response) {
var schemeId = null;
if (req.query.schemeId) {
schemeId = req.query.schemeId;
console.log(schemeId);
} else {
response.send('false');
response.end();
}
getCsrfValue(function(err, res) {
if (!err) {
_csrf = res;
console.log(_csrf);
request.post({
headers: {
'Authorization': '',
'Content-Type': 'application/x-www-form-urlencoded',
},
uri: 'https://www.xyz.site',
body: "schemeId=" + schemeId + "&_csrf=" + _csrf
}, function(err, res, body) {
if (err) {
console.log(err);
} else {
console.log("body of post: " + res.body);
const $ = cheerio.load(body.toString());
var txt = $('.schemeCheckResult').text();
console.log(txt);
if (txt) {
response.send('true');
} else {
response.send('false');
}
html += body;
}
});
} else {
response.send(err);
}
})
});
//______________FUNCTION TO SCRAPE THE CSRF TOKEN FROM THE SITE____________
function getCsrfValue(callback) {
request.get({
headers: {
'Authorization': '',
'Content-Type': 'application/x-www-form-urlencoded',
},
uri: 'https://www.xyz.site'
}, function(err, res, body) {
if (err) {
return callback(err);
} else {
const $ = cheerio.load(body.toString());
var txt = $('input[name=_csrf]').val();
_csrf = txt;
return callback(null, _csrf);
}
});
}
module.exports = app;