I want to have some kind of auth to make protected routes.
For example, the GET /forecastweather should be protected. While the GET /generalweather should not.
I read the express 4.x documentation (https://expressjs.com/en/4x/api.html) but I can't find an authentication function. I also looked in the req (https://expressjs.com/en/4x/api.html#req) documentation to see if there is an attribute to request I can use.
If I'm right express had basic auth function, but it seems to be gone. What is the best way to protect routes by some kind of bearer token.
There is no "best" way to do authentication. There are just multiple different ways and you have to decide which fits your situation the best.
First, you need to decide how you're going to deliver your credential which likely depends upon what type of client you're using.
Token in a cookie (often works best for browser access)
Token in a custom header (often used for programmatic access for APIs)
Token in query parameter (not as common)
Once you decide how the token is going to be delivered, you then have to figure out how the client is going to get their token. This would typically be some sort of form submission that contains credentials (such as username and password) and the return from a successful verification of those credentials would be the token.
To process this form, you'd create a POST request handler in Express and verify the credentials, returning a token if the credentials are valid.
Then, within Express, you'd create a router that contains the authenticated routes and add some middleware to that router that verifies that a valid token is present on the request before allowing the request to proceed. This will protect all the routes on this router.
Related
I may be a little confused about how backend servers work. Let's say I have a frontend React app with a login. The login information is stored in a database (i.e. MSSQL, MySQL, MongoDB) and I have a Node backend with routes for my app to fetch that information when a user is logging in or doing anything. When both my React app and server are hosted, I would make calls to the api and no confidential information (such as passwords) would be sent back to the client (just maybe a "success" message if the login information appears to be correct on the backend). My question is, what is stopping someone from finding the backend route and putting it into Insomnia to get the password or other sensitive information?
My first thought was to use express-session and auth on the backend to require a user to be logged in to an account to make such requests, but I think there are two issues with that:
How will that work when multiple users are logging in at once? Since the users are not technically physically visiting the api routes themselves, does session still know who is signing in to what account on the frontend? Will the second person logging in override the first person's session even though the first hasn't logged out yet?
If the auth doesn't kick in until a person is logged in, wouldn't someone be able to get the response password data from the login route itself?
Sorry if the question sounds dumb I'm just having a little trouble understanding the security aspect.
It sounds like there's a bit of a misunderstanding of how auth sessions work. There are two primary way sessions can work - either storing the sessions on the backend (older way), or storing session data in a cookie, typically a JWT (JSON Web Token). Cookies are bits of data that are passed from the server to the browser and anytime the browser makes a subsequent request to your server, it passes the cookie back too, so your server will always be able to get that data. The way this works for auth is the following:
A user signs into your application with credentials (username and password).
Your server validates the credentials by checking your database or wherever you're storing them and rejects the request if it fails. (Check out Auth0, Firebase Auth, or other auth services as doing this yourself can be a pain and open yourself up to potential vulnerabilities)
If the credentials are valid, the server generates a signed JWT token that includes data, like the username of the user.
The server responds with the body as well as a cookie containing the JWT, which the browser then stores.
The user requests some user-specific data from your server, and the browser sends the cookie with the JWT back to your server.
Your server validates that the JWT is valid by checking the signature. If it is valid, it uses the username from the token to get the user-specific data. If it is not valid, it rejects the request.
Because the signature occurs entirely on the server side (typically with some hashing algorithm and a secret key that you don't vend publicly), it would be nearly impossible for someone to spoof a JWT token signature. Therefor, your server is able to 1. trust that the JWT token is indeed valid if the signature is correct, and 2. find out what user is requesting data.
Here's a video that helps explain and visualize this: https://www.youtube.com/watch?v=soGRyl9ztjI
And here's a library for creating and validating JWTs in Node: https://www.npmjs.com/package/jsonwebtoken
Hopefully that answers your question!
what's a common approach of storing user sessions with Nodejs+Express and Firebase auth? I have Android and Ios app that I'd like to use the same logic on (later web as well), so I'd get the JWT token. I'd like to use that token as authorization for requests. Also I'd like to keep the user sessio and not require them to relogin again. I am not sure how to go about this, all of the Express Session resources I've found were on topic of web and cookies. I've stumbled upon MongoConnection a library for Express that presumably stores the sessions in the MongoDb, but how does the session work with non-web requests? Can anyone help me clarify this, I am aware that I am missing the point here as there is certainly an easy way to verify incoming requests and also have a session for the user to not have to login everytime.
Preferably I'd like to have an easy way to have endpoints that require JWT token access. Besides that also have a session of sorts. There is a function to verify tokens in the Firebase Admin SDK for Nodejs but it seems really weird to have to check the token manually in every request.
I treat sessions on the backend and front end entirely separately as I predominantly make RESTful apis. On the front end you can handle sessions however you like, e.g. you can start a session when a user authenticates with firebase auth, and set the user role maybe based of attributes on the firebase auth user. Use cookies, do whatever you prefer.
Then on the backend, on every endpoint just decode the token, verify it, check that the user has access to the resource they are requesting etc. Its common to write your own middlewares so that you dont have to repeat the decoding code. For further info on this approach, this might help. Its not weird to check the token manually on every request, its common practice to guarantee the authenticity of the request. Hope this is of some help.
To sum up, treat your front end session entirely separately from the backend. On your express server on the backend, on any protected endpoint decode and verify the token to determine if the user has access to the resource.
Backend sessions with firebase are a bad idea (due to it been serverless), its better to create a stateless restful api.
I'm in need of some advice on what's the best method I can use so that the routes on my server are only accessed by certain users.
My server has some simple routes"/example" and I'm using Express JS to write these routes. The people who will access these routes are a few and they will mostly be doing it from terminal with a curlcurl 123.45.678.901/example but I want to make it secure so that only a certain group of people can access that route.
What should I do? I'm new with this so I was looking into maybe adding a custom header to the curl but I don't know how to check in the route for that custom header and then I thought that might be too simple so I'm wondering if there's a better way that giving the users a "password". Grateful for the advice!
You need to require a credential in order to access the protected routes. The credential can be in the form of a token or password in a custom header, in a query parameter or a token in a cookie.
It's best not to put security credentials in query parameters and obviously, you should be using https to protect the credentials during transport.
If the route is only accessed via CURL, then a custom header containing the credential is probably the most straightforward way to do it.
For express on your server, put all routes that require auth on a specific router and have middleware that verifies the credential before passing control to the routes.
I'm currently trying to implement some authentication for my application, however, I have a quick question.
I set up some basic authentication on the backend, which sets a token and sends it to the frontend where it is saved in a cookie.
I read that the token is sent to the server any time I'm making an api-call, but I have trouble understanding how I'm supposed to do that.
I just read this question on stackoverflow and it seems as if the person that answers this question simply suggests two helper-functions which check if there is an item called token.
This seems like a bit of a security risk to me. Couldn't anyone just set an item called token which any random value in the local storage? Thus this person would gain access to protected routes?
If so, how would you make sure that the JWT is actually authenticated?
So, to break it down, my questions are:
Is what the answer above suggests a security risk?
How exactly to you send JWTs with your api-calls and how are they verified?
Is what the answer above suggests a security risk?
Your api should return a 401 error if a random token is used so you can handle this 401 error by clearing the token value in the cookie/local storage.
Edit: To prevent the user to access private routes with a self entered token value you may want to make an api request to check the token in the auth function of your private route (this is optionnal as a fake user will not be able to fetch the api anyway, btw keep in mind that the client have access to the javascript app code so he will always be able to "read" the restricted pages, unless you do SSR, that's why your sensitive data have to be server-side)
How exactly to you send JWTs with your api-calls and how are they verified?
Depends on your server side implementation i.e. jsonwebtoken or passport and passport-jwt works great.
On client side you'll send your jwt in the Authorization header of each request with a prefix like JWT or Bearer (depending on passport config).
Example using fetch :
fetch('/api', {
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ...'
}
});
In my app (Mongo,Express,Node,React), I'm currently authenticating users from the client to the server using JSON Web tokens. However, I want to be able to have two different types of users access different halves of the app. What is the best way to go about this? I currently have both types of users saved in the same model with a boolean that differentiates them. To clarify, different types of users would be able to access different API's as well as different portions of the client side app.
Is there a package that handles this? JWT feature?
There are 2 ways that you may do this:
When you are encoding the JWT token, encode the user role also.
When you decode the JWT token and get the user's ID, for example, query your data store to get that user's role.
Most of the packages will allow you to define what you want to encode.
Tips:
Always set an expiry on your tokens. It's simply a date stored on
the JWT. When you decode the token just make sure that the date is
in future, if not deny access.
Create a middleware that checks the user's role. For example:
router.get('/restricted-area', requiresAdmin, (req, res, next) => {
// only admin can access this
});
function requiresAdmin(req, res, next) {
if(req.user.admin !== true) {
res.status(401).end();
} else {
next();
}
}
Wanted to add a little to the suggested answer. A lot I am taking from how Auth0 uses jwt. You might want to play with it so see how they handle authentication and protecting their routes. Another thing that really helped me understand ways to use jwt was playing with the debugger on the jwt website.
Allowing users to access different API endpoints
A jwt token can be decoded by anyone. Anyone can see what is on the token. The important part of a jwt is that it has a signature. If someone wanted to take a token, change the information and then access your api, then the signature would be messed up and that token should be rejected.
All you need to do is create a route middleware. If a route is protected the user sends the jwt in the header. The middleware will do 2 things:
Check the signature of the token to ensure the token is valid and has not been tampered with.
Decode the token to see what is on the JSON. Since a jwt is just a JSON you can add any property to it you want. Add a property permissions and set what level that users permissions are. Here is a tutorial from auth0 about how real life companies like slack could use jwt tokens to define what a user can and can't do. A lot of the same principles apply to exactly what you want to do. Auth0 with multi tenant apps
How can I restrict users client-side using React?
I saw this question in the comments and will throw the answer here in case anyone was interested. If someone really wanted to, they can take their token, change it, and get to any visual component (in react). The reason that is the case is you don't want to keep any token signature secrets on your client. But even if someone did change their token, they wouldn't be able to do any damage. If they tried to send a request to the server, their token would be rejected and your api would be protected.
React Router and Dynamic Routing
For the 99.9% of your users that don't mess with their token, the best way to decide what parts of the site they are allowed to use is by using react-router. Since React is a single page application there is only one static html file that will send your build to the client. With other frameworks different routes on your server will send a different page at different static endpoints. To mimic this page behavior with react, it is very common that people use React Router. React Router creates dynamic routes so when users insert endpoints into the browser it can mimic how typical static sites work.
It can also be used to restrict users from accessing certain components. Once a user logs in, you can send the decoded token information and save it to your react state. One of those would be your permissions parameter. With react router, when a user attempts to navigate to a location that requires permissions you can reference their state and redirect them either to the protected component or back to an authorized catch, back to where they came from, the login page, etc. Basically wherever you want.
Here is a, slightly confusing implementation on the react router documentation site about implementing restricted endpoints.
Another tutorial from auth0 using react router to restrict users. Scroll to the header Process the Authentication Result