Render based on server's response - node.js

I am a new SPA developer in React, and I'm building a full-stack web application, [back-end and front-end], while planning, I stopped at a point that I couldn't find a convenient method for.
On the Login page, after the user enters his username and password, and hits submit, the form will send a POST request to the server, the server will verify the information provided, if the username and password were true, the server will ask the database to see if the user has activated the two steps verification, in case the user has activated it, the server will send a verification email to the user...
This is well-known, but the point is, how the server is going to tell the client (the React web app) that "hey react, you should render a box of "enter the code sent to your email" rather than rendering the user profile page because this user has two-steps verification enabled.
What is the convenient and the most logical way of writing this response from the server-side?
I was thinking of the following response:
// this is the response from the server after submitting the form (sending an AJAX POST request) HTTP code #200 code
response:{
UI: {
showEmailVerificationBox: true,
}
}
Is there a standardization for these kinds of responses? where the server wants to tell the client to do something in its UI?

Related

In sveltekit, How can I get "load's fetch" from client side code?(like *.svelte)

I'm making private homepage working only for login user.
When user login success, API server return token and save it to cookie.
After that, token was added to all fetch's request header at server-side "handleFetch" hooks.
All works fine with server-side rendering. But At client-side rendering needed position, I can't use "load's fetch" and also can't get token from cookies by default sveltekit functionality.
How can I solve this?

firebase onAuthStateChanged infinite loop node js

I'm using firebase to sign in my users on my node js app. I would like to see if the user is authentificated or not and after it redirect to the page I want (login if it not logged or dashboard).
But when I redirect user (if it not logged previously or session expires) it's looping on the same page (send redirect of the login page everytime when I'm on login page).
My function that I use actually :
function authenficated (req, res, next) {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
console.log("connected" + " " + user.uid);
next()
} else {
console.log("disconnected")
res.redirect('/') //loop on / page
next()
}
});
}
I would like a function that provides if my user is logged or not, if it logged my node backend return to /dashboard or other pages that I want and if not it cannot access to dashboard and it return automatically to / or /login
I specify I don't use React or Vue, I use simply EJS to display my pages
Thanks for all
This function/sdk is meant for frontend applications and not backend apps. You need to the admin sdk for that. You can use cookies and the admin sdk provides a function to create cookies. After a signin you attach the cookie to the headers and it will be send by the browser on every request. If the cookie header is empty than you know the user isn't signed in. To logout a user you can add a head method to clear the cookie.
To use backend function you need to use the admin sdk. This function is a front end function (web sdk ).
You can use onAuthStateChanged on the front end and redirect them from the front end. Remember onAuthStateChanged will fire on every page load.
OR implement cookies like the previous comments.
OR
Send the id token from the client via http request (fetch or axios) and verify server side using the admin sdk. Here is the specific link. This solution would require you to load something on the front end though and then send a http request to the backend, verify, then send protected resources after.
Cookies on the other hand are sent to the backend with every request, so if no cookie is present on the page load request then obviously there is no user. Or if the below function fails then server wont send protected resources. (this is explained in the link above for cookies)
getAuth().verifySessionCookie(sessionCookie, true /** checkRevoked */)

How to made Signup and Login Post Request on same Webpage

I am new in Nodejs and developing a login and signup page. But the thing which is different is I want my login and signup on same post request
and Login Page is
What I next do is in both form I add my action to home page but inside
app.post("/",function(req,res){
});
How will I differentiate between request is sign in or signup.. I want to do on same page and also I did not want to change my Url on browser while doing that
Id recommend separate paths for both, but if still you want to achieve this with single request path. Then you need to add an identifier to differentiate between signup / signin requests.
you can pass it in body of POST request :
{
username: xyz,
password: abc,
reqType: 'login'
}
Once you receive this body at you server, you can just simply check the value of req.body.reqType variable and perform the logic.
You can also pass the unique identifier to differentiate between signup / signin requests as a request header. At server side you can just check for req.headere.reqType and perform the desired actions,

How can I return server side error to the client's HTML page in Express/node js?

I am creating an web app I which the user requests to create an account. The request from client's page will reach the server and query the database. Now what is the proper way of displaying User already exists error in my registeration page. In short, how can I send server side errors to my clients in Node JS?
There are some options to get what you need. The approach that I would not follow will be using the http protocol and sending a 500 response for example.
One good approach would be creating a status and a message fields in your response.
You could use code 200 for the sucessful requests and a different code for the rest. You could have a dedicated code to inform the api user that the backend coud not insert the data.
Example response:
{
code: 789
message: "User could not be inserted"
...
}

Preventing man-in-the-middle attacks with user authentication (Node/Vue/Passport)

I currently have a webapp I'm writing in Node/Vuejs with Passport handling authentication, and I've run into a problem. I was thinking about how I have authentication currently set up and I realized I had a glaring security hole.
In short, I have my Vuex store hitting a local API endpoint /api/me. That endpoint does a simple return of req.user. For the sake of brevity, a typical response looks like this:
{
username: 'Bob',
roles: [] // normal user has no roles,
email: 'someguy#bob.com'
}
My admin route /admin has a beforeEnter check, as shown below, that incorporates this check using the Vuex store, so I can have a cached version of user data accessible on the frontend.
{
path: '/admin',
name: '/admin',
component: Admin,
beforeEnter: (to, from, next) => {
store.dispatch('getMe').then(() => {
if (store.getters.user.roles && store.getters.user.roles.includes('administrator')) {
next();
return;
}
next({ path: '/' });
});
}
}
Here's the thing though - I realized that someone could easily game the system. In fact, I tried it myself with a test, non-Adminstrator account, and I was able to get in by returning the following from a local server set up for this purpose in Postman:
{
username: 'Super Admin Joe',
roles: ['administrator'] // normal user has no roles,
email: 'admin#bob.com'
}
And viola! The user now has full access to admin pages.
My question is, how could I prevent against this?
I need to check that the user is authenticated on every page, but a potential attacker could quite easily proxy any request (in this case it's /api/me) to make themselves any user they want. They can login normally with their own account, open the Network tab and copy the response payload, then change the user data as they wish. There needs to be some sort of encryption between the frontend and backend when checking a users' logged-in status, I believe.
I tried thinking about how I could prevent this from happening, but anything on my end (server-side, at least) seems useless as any request could easily be redirected to an attacker's local machine.
Any advice on how to "sign" my requests to make sure they aren't being proxied? Thanks in advance!
You shouldn’t have to be signing the response body of an api request. The typical way to do authentication is to establish a signed session cookie that acts either as an identifier to session information in an external database, or contains session information itself. This cookie should be in the header of your response and passport should give you a way to administer this cookie without you even realizing it.
This way the user can’t tamper with the information sent from the server in a way that’s easy to detect, and since it’s a cookie it will automatically be sent with each request by your browser (although if you’re using some AJAX library you may have to explicitly specify you’d like to send the cookie). What MadEard was referring to in the comment is where the cookie information is able to be accessed using passprt which is the ‘user’ property in the ‘req’ object.
After reading your github files:
server.get("/admin", function(req, res){
if(req.user && req.user.roles.includes("administrator")){
//user is an administrator, render the admin panel view
}else{
//is not an admin, redirect or send error message
}
});
In every Express route, after authentication with Passport, you have the req.user object.
It is established by checking the request cookie connect.sid, and checking which session this cookie belongs to on the server.
As such, you can trust that in any Express route, the object req.user contains the information relevant to that cookie and you can act upon it.
A little note: doing server-side validation should become a reflex for you over time.
The client is meant to display information. If, at any point, you are making the client take any decision that could be a security liability, take a step back and think it again.

Resources