How to authenticate each API for authorize user? - node.js

I would like to authorize users for each api call.
For example:
app.post('/user', isAuth('user.write'), controller);
Above api requires user.write role, so how to check everytime that user has this role or not? isAuth function validates that user.
As per me we can save all the users roles at the time of login into redis and in each api call we fetch it from redis.
But roles are more then 1500, won't it make it heavy? Or should I check database for each api?
Or any other better way so I can easily validate each api for user?

You could utilize JWT tokens.
Your API would then issue a JWT token to a user that has the roles.
The user then provides this token for every request, and you don't have to make calls to redis, because you just just decode the JWT token and check out the roles from there.
The JWT token is signed by the server, and can't be modified by the client so you know that the roles are the roles actually provided from the server.
Read more about JWT security in this article
A popular library for working with JWT tokens in node is node-jsonwebtoken which has over 10000 stars on GitHub.

Related

REST api authentication using firebase admin sdk

I have a REST api and the authentication is done using jwt tokens. To make may api more secure (users and authentication mechanism) I would like to use firebase authentication. I would like to know can we use firebase as a authentication server for my REST APIs.
My understanding is that the client app will send the username and password to the firebase server and they will provide a token. Using that token client app will send an api call to our server. I need to integrate firebase admin SDK in my server and validate the token using admin SDK to get the data from my database.
Please correct me when I am wrong.
Also, i have a concern that how to manage refresh tokens to keep my app logged in.
Please help me to integrate this in the right way, and I am using nodejs/expressjs to create the APIs.
can we use firebase as a authentication server for my REST APIs.
Yes, it's one of the services they provide: https://firebase.google.com/products/auth/
My understanding is that the client app will send the username and password to the firebase server and they will provide a token.
Correct. The usual Firebase auth is done entirely client side.
But if there is a specific auth mechanism you need such as LDAP/AD or some other form of enterprise shenanigans, then you would need to create your own tokens that the client will use to authenticate: https://firebase.google.com/docs/auth/admin/create-custom-tokens
Using that token client app will send an api call to our server.
Correct. Once the client has successfully logged in and retrieved their ID tokens, you on the server side need to verify the ID token: https://firebase.google.com/docs/auth/admin/verify-id-tokens via middleware.
Also, i have a concern that how to manage refresh tokens to keep my app logged in.
You need not worry about that so long as the client uses the appropriate method to retrieve the ID token. For example, on the Web side the client would call: https://firebase.google.com/docs/reference/js/firebase.User#getIdToken which states (emphasis mine):
Returns the current token if it has not expired, otherwise this will refresh the token and return a new one.
As you can see, the client side Firebase SDK handles everything for you. There is no need for you on the server side to keep track of ID tokens, refresh tokens, or anything really. All you need to do is verify the token, that's it.
Please see my previous answer for more details on server side verification: Firebase authentication using NodeJS

Looking for JWT Auth microservice example

I am wanting to build a authentication/authorization service using NodeJS, Mongo, and JWT. This service would be a micro-service that handles requests not only from my API Gateway before allowing requests, but from other services that might want to check auth and roles. I am assuming that all other services will use this Auth Service to validate the JWT as well as roles, etc.
Hopefully this diagram better explains what I am looking for.
Can anyone point me to a resource that might help me learn how to do this with NodeJS?
If you have a single client application then you can do following steps
Make one microservice for authentication that generates jwt token.
The jwt contains all essential user information in its payload, ie Role, UserId etc.
The jwt token will be sent in Authorization header for every authorised request.
Before processing any request you can validate and decode the jwt token using middlewares. Now you can set the user's info in req object easliy and can easily access users role and its id in your controller.
if the token is not valid then you can throw error in middlewares and it will provide json response of unauthorised.
You can call the authentication api to validate and decode your token or you can write 3 to 4 line of code in every microservice in middleware.
Here are some links for sample implementation of jwt, you should customize these sample code according to above steps.
5-steps-to-authenticating-node-js
authenticate a nodejs api with json web tokens
If you have multiple client applications
You should use openid connect standard that provides single sign on solution to authenticate multiple application with same username and password.
here is a openid connect playground to understand the authorization flow.

REST API social logins [express.js]

I am not sure what is smart to do.
Should I check if facebook access token is valid inside in middlware or maybe is better solution to make route which check if facebook access token valid and then return JWT access token to allow user access?
If it's a rest api, do not use logins or sessions. Just send out jwt tokens. Embed all required data in the tokens.

How to combine node express with passport providers and jwt?

I'm writing a single page web app using express and react.
I am now trying to choose the way to authenticate my users.
I want to let them register and log in with email and password and 3rd party provider like Facebook, Google etc...
I read some articles about passport and jwt (express-with-passport, jwt-with-passport), but none of them combined jwt and 3rd party provider.
The only way I could think of is to save the tokens in my db, and for each request to compare them (tokens provided by a 3rd party and tokens generated by myself using jwt)
Saving the token from a provider in my db and compare with each request makes sense, but using jwt I just need to verify the token without accessing the db.
How can I differ the tokens that I receive from the client? How can I tell when to access the db (for provider tokens) and when to verify using jwt?
EDIT:
The way of implementation I was thinking about is as follows:
- Username & password: Upon login, generate a token (using jwt) and send it to the client. Every request will include the token and the server will verify it.
- 3rd party provider: Let's say that the user is authenticated with Facebook. My server receive the token (using passport-js) from Facebook. Now I need to send the client its token. I could send the token I just received from facebook, but then how can I verify the token the client send to me afterward on every request?
So I could generate once again a token using jwt and work just like described above.
Is this a good implementation or am I missing something? I couldn't find
a full tutorial that describe all of those aspects.
Rather than using a token that an identity provider might give you, you might consider generating your own tokens based on a successful login callback to your application. Issue new tokens on every request for sliding expiration, and possibly consider the use of refresh tokens.
In your DB, you could store the authentication method for a given user (Facebook / Google / etc.) when they log in. When you receive a request with an invalid token, query for this auth method from the DB, then redirect them to the respective identity provider for re-authentication.
This will avoid DB lookups for most "normal" JWT validations for your app and gives you the full benefits of the stateless nature of the token.

Should my app issue it's own access tokens, when using external oauth2 provider (facebook)?

I would like to give the users a possibility to login with some external oauth2 provider (facebook) in my app. The client's part is running on mobile device in a native app.
I am not sure which of the approaches below should I prefer ?
Should the client send the user's access token by facebook with each request ? At each request backend asks facebook to validate the access token. Based on the validation's result, backend performs authorization and return corresponding result to the client.
Should the backend ask facebook to validate the access token only at user logon, then issue its own access token, return the access token back to the client and client will use this access token at making requests to the server to avoid contacting facebook at each request ?
I have read some questions about how to implement the auth with facebook and most of the devs are using B, but I haven't seen any explanation why is it good/bad to use A ?
What I see as benefits of the solutions:
backend doesn't need to care about issuing, refreshing, validating access tokens since this is done only by facebook's authorization servers.
this solution seems to be more effective, since it does not require to connect to facebook at each request.
Security tokens issued by Facebook are signed with a digital signature. The API server only needs access to the public key to validate the signature. There's no need at all to contact Facebook after the user authenticates.
A reason to issue your own tokens after the user signed in with Facebook could be to add claims to the token. But obviously having your own authorization server comes at a cost. It's up to you to weigh the pros and cons.
If you do decide to have your own authorization server, make sure not to write your own! There are open source options like Thinktecture IdentityServer.
I will vote for option B and here is my explanation,
Your API must authorise the request every time with some auth token , which cannot be external provider token, in such case anyone with an access token (eg: other developers) of other provider can access your api, basically there is no auth here.
When your sever issue access token, it's easy to validate and when needed could be revoked easily (eg: on password reset)
While authenticating , your server has fully control over issuing access token , so the validation is made only once and doesn't have to do every time while calling the API.

Resources