Angular 6 with steam-passport - Auth Guard Issue - node.js

I'm using steam-passport to loggin.
So basically, I go to localhost/auth/steam, this redirect me to steam service, then go back to localhost/auth/steam/return, and from there, I got my req.user as expected :
router.get('/auth/steam/return',
passport.authenticate('steam', { failureRedirect: 'http://localhost:4200/' }),
function(req, res) {
res.redirect('http://localhost:4200/'); --angular port application
console.log(req.user) -- I have all my datas
});
Again, when I open my brower and I go to localhost/api/isLoggedIn, I have my req.user as expected:
router.get('/api/isLoggedIn', (req, res) => {
if (req.isAuthenticated()) {
console.log(req.user)
if (req.user.db) {
res.json({user: req.user.db, success: true})
return
}
}
res.json({success: false})
})
The issue is when I'm using it with Angular.
I'm forced to do a window.location.href = "http://localhost:8080/auth/steam"; when I click on the loggin button. And again, I have my datas when the steam service answered to me.
But when I'm trying to access it from Angular:
isAuthenticated(): boolean {
let obs = this.http.get('http://localhost:8080/api/isLoggedIn').subscribe(data => {
return JSON.parse(data._body).success -- this is always FALSE!
})
}
How to manage the issue? From the brower, it's ok but from Angular, it's look like it's not the same guy who clicked on the button ahah.
Thanks for any future answer.
EDIT:
I invenstigate a bit, and I don't have the same session when I go over the brower to /api/isLoggedIn and when I make an http get request from Angular, how to link both?
session id for browser : EvbuWUZ7vceCxHsm7npb6572bLe-1lRC
session id for Angular : it change every time I make the request..

Your isAuthenticated() function is always returns undefined (which can be treated as false).
Look into your function. Your function is not returning anything. The return statement is inside of async function.
Try this.
isAuthenticated(): Observable<boolean> {
return this.http.get('http://localhost:8080/api/isLoggedIn')
.pipe(
map(data => !!JSON.parse(data._body).success)
)
}

Related

endpoint don't work, doesn't return anything

¿can you help me to understand this?
If I have an endpoint in a specific route it will display in the browser the expected content, but with the same code just modifying the endpoint it doesn't return anything.
The only change that I do is the route of the endpoint, the rest of code is the same in both cases.
¿Why this happen?
The code displays in the browser the content of a json file:
this way it doesn't work:
It doesn't show an error, just don't return anything.
localhost:3000/v1/people/partner
app.get("/v1/people/partner", (req, res) => {
const peopleInVisual = PeopleController.getAllVisualPeople();
res.json({ peopleInVisual });
});
In this way it works fine: notice I just have changed the hello at the endpoint
localhost:3000/v1/hello/partner
app.get("/v1/hello/partner", (req, res) => {
const PeopleInVisual = PeopleController.getAllVisualPeople();
res.json({ PeopleInVisual });
});
Thanks!

Express JS - Redirecting If MongoDB id doesn't exist / Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

Within my Posts routes, i'm making it so that the user can go to posts/:id to retrieve information about the post with that ID, however i'm trying to make sure that if the user goes to a post that doesn't exist, he gets redirected back to the posts index route. My issue is that the server is going through the entire router.get function instead of redirecting the user and stopping.
router.get("/:id", async (req, res) => {
if (!mongoose.isValidObjectId(req.params.id)) {
console.log("Test1")
res.redirect("/")
res.end()
}
console.log("Test2")
try {
console.log("Test3")
const post = await Post.findById(req.params.id)
if (post == null) res.redirect("/")
res.render("posts/show", { post: post })
}
catch {
console.log("Test4")
res.redirect("posts/index")
res.end()
}
})
If I go to the route posts/weiqeiqwie (which isn't valid) it prints all of the test console logs. What can I do for the code to return after the error?
I'm still a bit new to using express, so sorry for the dumb question.
you cant redirect AND render at the same time.
this is what this part of the code does when post is null :
if (post == null) res.redirect("/")
res.render("posts/show", { post: post })
adapt it like this, so that now when post is null it only does the redirect part.
(never forget the return)
if (post == null) return res.redirect("/");
res.render("posts/show", { post: post })
the same goes for the redirect line 3 :
it should be :
if (!mongoose.isValidObjectId(req.params.id)) {
console.log("Test1")
return res.redirect("/")
}
also res.end() is not required. you can remove it from everywhere.

Why isn't localhost responding to render?

I am using Knex JS for user authentication in order to get email and password from the user and connect to PostgreSQL to check for authentication.
router.post('/login', async (req, res) => {
knex.select('email','password').from('users')
.where('email', '=',req.body.email)
.then((data) => {
const isValid = bcrypt.compareSync(req.body.password, data[0].password);
if (isValid === true) {
res.render('index-v1');
}
});
});
But the render function is not rendering the index ejs file but rather the localhost is not responding.
Thanks in advance for the help.
So, as the comments suggest, there are two possible paths not covered by your route, which is apparently leading to a lack of response from the server. Remember, if you don't tell it to respond (with res.render or similar) it won't respond, leaving your client hanging.
router.post('/login', async (req, res) => {
try {
const data = await knex.select('email', 'password')
.from('users')
.where('email', '=', req.body.email)
const isValid = bcrypt.compareSync(req.body.password, data[0].password);
if (isValid) {
res.render('index-v1');
return
}
res.render('error-page');
} catch (e) {
res.render('error-page');
}
});
In other words: if the password is incorrect, we still need to respond to the client. If there's some kind of database error (or the user doesn't exist, say) we still need to respond to the client. Exactly how you respond is of course up to you, but that's the kind of structure you need to think about.

Axios 'GET' request is pending but it never reaches the server

I am using axios on my React app to get data from my server (Node). My GET request stays pending in chrome developer tools and does not reach the server if I refresh the app on the provided route (e.g., http://localhost:3000/category/5d68936732d1180004e516cb). However, if I redirect from the home page, it will work.
I have tried different variations of making sure I end my responses on the server end of things.
Several posts have had related problems (e.g., request not reaching the server, POST request does not reach the server) but unfortunately not been helpful in my situation.
Here is my main call in my react app:
componentDidMount() {
console.log('I am here!'); // this gets executed even on page refresh
axios.get(`/api/categories/${this.props.id}`)
.then( (res) => {
this.setState({
title: res.data.category.title,
module: res.data.category.module ? true : false,
...res.data
})
}, (err) => console.log(err))
.catch(err => console.log(err));
}
On my back end I call this function after going through user verification:
module.exports.publishedCategories = async function(req, res) {
try {
// some code that I removed for clarity
res.json({
category,
children,
flagged: flaggedCategories
});
} catch(err) {
console.log(err);
res.sendStatus(500).end();
}
}
Some more code regarding my routing:
index.js
<Route
path='/category/:id'
render={ (props) => {
return <Category id={props.match.params.id} />
}}
/>
I do not get any error messages...
I was overzealous with my initial solution of switching to componentDidUpdate(). This only worked for page refreshes but not for redirects (i.e., I had the reverse problem). My final solution is as follows:
componentDidMount = async () => {
setTimeout( async () => {
this.loadCategory();
}, 10)
}
componentDidUpdate = async (props, state) => {
if(props.match.params.id !== this.props.match.params.id) {
this.loadCategory();
return;
}
return false;
}
loadCategory = async () => {
let result = await axios.get(`/api/categories/${this.props.match.params.id}`);
this.setState({
title: result.data.category.title,
module: result.data.category.module ? true : false,
...result.data
});
}
I am not sure why adding a setTimeout() works for componentDidMount().
As per the documentation componentDidUpdate(), it is good for netork updates however you need to compare prior props with current props.
Unforunately I am not sure how to get around the setTimeout() hack but it seems to work.

nodeJs express petitions from ajax don't show error's page

I have a configuration to serve a website with an error handler. It works fine with app.post requests, but it does not work with ajax petitions.
Here is my error handling middleware with an example of bad path error that works correctly:
//Bad path error
app.get('*', function(req, res, next){
next('404'); //This works fine
});
//Errors control Middleware
app.use(function (err, req, res, next) {
if (typeof (err) === 'string') {
var lang = require(path.join(__dirname, '_public', 'errors', 'lang', process.env.LANG + '.js'));
return res.render(path.join(__dirname, '_public', 'errors', err), {lang});
} else {
log.error(err);
var lang = require(path.join(__dirname, '_public', 'errors', 'lang', process.env.LANG + '.js'));
return res.render(path.join(__dirname, '_public', 'errors', '500'), {lang});
}
});
when I navigate to a wrong url (some url that isn't defined on my server) it goes correctly to the defined error page (404, that is an .hbs). The problem is that this method doesn't seem to work with ajax petition like the next one:
jQuery.ajax({
type: 'POST', //I have the same problem with 'GET'
url: '/componentName/methodName',
data: {
accessToken: localStorage.token
},
}).then(function success(data) {
//TODO
}, function error(err) {
console.log(err);
})
This piece of code is for server side:
app.post("/componentName/methodName", function (req, res, next) {
var token = req.body.accessToken;
var decodedToken = jwt.decode(token);
var user_id = decodedToken.payload.user_id;
model.getTasks(user_id).then(function (modelData) {
res.send(modelData); //This works fine
}, function () {
next('500'); //This broke the page and doesn't show error page
});
});
What could be the problem for not showing the error from ajax? Is my syntax correct?
new: The problem must be on the ajax success, because if I change the 'post' by 'get' in ajax and the app.get route I still having the same problem, but if I call the method directly from URL (not ajax) it works. Any idea?
new2: If I put this code on success:
jQuery('body').html(data);
it shows the error page after a few seconds. I need to do this automatically (and without those fews seconds) when any error is trhowing from the server, because I don't know if it will be ok or if is an error and the lag seconds is a problem too. Probaly anything on the server could be wrong? and it inject the error page inside the older page, so isn't a solution
model.getTasks(user_id).then(function (modelData) {
res.send(modelData); //This works fine
}).catch(function () {
next('500');
})
Use catch block

Resources