How to provide authentication for a single user (Node, Express)? - node.js

I am currently working on an app with a React frontend and a Node/Express backend. There are certain functions of the app that I only want an admin user to be able to use, so I want to implement an admin login form that takes a username and password. This would be the only user that this app has.
How would I go about implementing this? I've looked at technologies like passport.js and express-basic-auth, but I'm wondering if there's a simpler way to implement this since there is only a single user. Any advice would be greatly appreciated!

If you wanna do it by yourself then whenever the user logs in the application, create an authtoken for the user and save it in the backend and send the authoken as the response for successful login. Further save the authtoken as a cookie on the frontend. Next will be while performing any action you need to send the authtoken to the server. If that authtoken is present on the server side you go on with the action or else send the response error saying that the authtoken is invalid of something like that. On loggin out of the application remember to expire the cookie and also remove the authtoken from the backend.
You can add this if you want where if the authoken provided is incorrect you can simple remove the authtoken from the backend and redirect the user to login page expiring the cookie from the frontend.

Related

Login functionality from external API in React with Node.js

I’m having trouble figuring out how to get Node.js backend tokens into React.js frontend local storage. To login a user will use their credentials though an external websites API using the Oauth2 flow, this will be the only way to login into the application.
Currently, the user clicks a button which opens a new window in the authorization URL where the user will grant privilege. Once granted, the user is redirected to the backend endpoint which goes through passport.js and gets the required access and refresh tokens sent from the external API. This is then stored in a session on the backend database. What I want, instead, is to not store a session on a database but instead implement JWT and store the user’s data in local storage. With the current flow, its just not possible to do this and I haven’t found the right documentation to work it out.
There are many websites that implement it the exact way I want but tracking down the way they do it has appeared to be a challenge in on itself.
So instead of using passport.js, which was causing a plethora of issues, I decided to implement the Oauth2 flow myself. Instead of doing ALL the work in the backend, I broke the flow into different parts.
Originally, I sent the user to the backend where they would recieve an authorization token there. This turned out to be troublesome, instead, request an authorization code on the front end. For example, send the user to the Auth path and redirect the user back the the front end once privileges have been granted. Wait at the frontend callback for a code, once obtained, send a post request to the backend with that code and any other data in the body.
When obtained at the backend, trade that code for the access token and respond to the post requst with the neccassary token and any other data that needs to be sent back e.g. profile name, picture, date of birth. You can the implementn the JWT flow and no database is required to store any session or tokens, all can be stored client side securely.

What's the Nodejs backend routine for "Register / Signin with Google"?

I'm using a Express Nodejs backend + React frontend set up and tried to implement a "Register / Signin with Google" function, but I do not understand what to store in the database after the user is authenticated. In the ordinary register with email approach, I send the email + password to the backend when I register and check if both the email & password match when the user login.
However, I don't know what to store in the db if one is registered with Google. I have already implement part of the google auth with google by following this tutorial in the frontend side, here's my code:
import * as queryString from 'query-string';
const stringifiedParams = queryString.stringify({
client_id: 'MY_CLIENT_ID'
redirect_uri: 'http://localhost:8000/protected_home',
scope: [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
].join(' '), // space seperated string
response_type: 'code',
access_type: 'offline',
prompt: 'consent'
});
const googleLoginUrl = `https://accounts.google.com/o/oauth2/v2/auth?${stringifiedParams}`;
return (
<a href={googleLoginUrl}>Login with Google</a>
)
But then what's next? I've successfully pass through the auth process and redirected back to the protected_home page. But this only means that this user is a google user, what kind of information should I store their information in backend so that it indicated that the user has registered an account in my backend with this google account?
Also, is is possible to move the logic above to backend? Since google will redirect back to my redirect_urilike this http://localhost:8000/protected_home?code=CODE_IS_HERE, I need to browser to extract the information in CODE_IS_HERE. So it seems impossible to move the login logic to backend, any solution?
What you need to save is user's unique id, his email or phone, and some other user data for your project.
This is just to know if the user already registered or to know the current user in backend.
From backend, you can just set a middleware to verify the token assigned from google.
Then you will get the user's id and you can find a user from your database, if exists, the user is authenticated.
Signin with google.
Get redirected with CODE
Send CODE to backend
Backend will get user id and email with the CODE using google api.
Save user and generate token.
Send the token back to your frontend.
Then the login or signup process is finished.
Basically you should not write it from scratch as there are libraries that deal with Oauth2: PassportJS, openid-client, Grant, OAuth2-client-js. Those should handle all the below steps except storing actual details in your own database.
In general there are some basic steps when implementing third party oauth2 authentication:
Understand well how Oauth2 works https://www.rfc-editor.org/rfc/rfc6749
Redirect to your server from client (react)
Request authorization by redirecting to Google
Get authorization code which will be added to a url in a redirect from google back to your server
Exchange code for an access token (POST)
Use access token to get user profile details from Google (POST)
Save user details if they do not exist yet in your database - in theory you could skip this part
Create session/token and send it back to client (React) - it is another redirect.
You could also not store any user details on your server and just pass back the token obtained from Google to your React app (client), but then you'd need to check if it is valid on every request to your server. Which is why it is simpler to create your own session token and send it to the client.
There are more details as this is quite a topic to start with but RFC6749 should fill in the gaps.

Steam authentication API, passing data back to Angular

I have this problem with Express(NodeJS)/Angular web app where I rely on Steam's login authentication. Essentially when the user clicks "Login" he's redirected to the Steam authentication(Steam's website), once logged in the user is redirected back to a specific route on my backend called /verify. Once the user hits /verify there are session variables containing necessary user data to access. Therefore I use JWT to generate a token with this data to send back to the client(Angular in this case).
The problem is sending this token back to the frontend(the client) to save in local storage.
Any help is highly appreciated! Currently, I pass the token via a query string with a redirect back to the frontend, but this doesn't seem like a good solution.
Maybe I should stick to server-side sessions and write HTTP routes to GET user data. The problem with this approach is once again the client is completely unaware when the user authenticates himself on the backend, since the only callback is triggered is on the backend.
EDIT:
Tried another approach, however once again unsure of it's the right way to go both code-wise and security-wise.
Redirect the user to the Steam authentication page.
Wait for the authentication callback on server side, in my case it hits the route '/verify'.
Once at /verify the session cookie is already set, therefore I redirect the user back to my Angular app to a specific route called '/login'.
On /login the user requests a token based on the session cookie on the server, the token in my case is a JSON Web Token(JWT).
Once the token is saved in local storage I simply redirect the user to any page in my Angular app.
If this is the wrong way to do it, please let me know!

How to use Passport & JWTs on client-end for authorization?

I'm currently creating a custom CMS for a friend's soccer team. The architecture is as follows:
On the back-end I've an API that interacts with the database (mongoDB).
On the front-end I've an express server that serves the pages using the templating engine handlebars.
Currently I've managed to authenticate requests to the API using Passport and JWTs, which is fine for querying the API, on login I'm storing a JWT with permissions in the cookie storage within the user (it's static pages and not a SPA so I cannot access local/session storage).
My issue is that I am struggling how to implement authorization on the client end for access to the admin panel. Should I decode the JWT on the client-end and read the user role then serve the pages if the admin pages if the user is an admin or should I be sending every request to access the admin section of the front-end to the API for a verification check then serve the files.
Any help would be greatly appreciated, thank you.
I think using a token authentication approach is more suited towards making requests via XHR, rather than hard reloads. The approach you are taking seems to be more suited to a session based authentication strategy. I would use passport-local and authenticate with a user name and password. Once authenticated the user is stored server side in a session variable. You could check the role from that and redirect server side.
If you were to stick with a token you could save it in local storage and then have a script on your admin panel that would first grab the token from local storage and then make a GET request to the server with the token in the header. If the token is valid send back the data to populate the page, otherwise send back an error and redirect from the front end. To get around showing an empty admin panel while checking the validity of the token you could show a loading screen until the request completed.

App/API authentication approach advice

I'm building a mobile app (Ionic/Cordova) and it will call an API (NodeJS) and I'm trying to come up with a simple and effective user authentication approach that can both:
Sign the user in to the mobile app and
Protect the API so that only a signed in user can call the API
The API can identify which user is calling it
Ideally, I'd use something like Auth0 to sign the user in to the app because I don't want to deal with passwords etc.
So I understand I can build my HTML5/Javascript app and using Auth0 and it will log the user into the app, but the part I'm trying to understand is how do I set it up so when user is logged in and their app calls the NodeJS API, the API code will know who the user is?
Can I just use the NodeJS passport module for Auth0 and just pass the tokens from the app to the API and like magic it will work? Or will I need to do something different in the API itself like build an oauth mechanism?
Any advice on how to protect the API in this scenario would be appreciated. I ideally don't want to build my own authentication/token system in the API.
Yes passport can help you to develop siple authnetication mechanism too. like username passoword. login once and stay logged in for some time.
check this tutorial
To get the tokem you have to add signin API. in the signin API you verify username and password. then generate a jwt token and pass to client.
var token = jwt.encode(user, config.secret);
Now In you mobile app At client side you can save as cookie or local storage .
window.localStorage.setItem('token', 'the-long-access-token');
Then after whenever you call API which are restricted. you pass the token. like this
var token = window.localStorage.getItem('token');
if (token) {
$.ajaxSetup({
headers: {
'x-access-token': token
}
});
}

Resources