express elegant way to restrict resources belongs to specific user - node.js

I found a lot of thread about permissions/role based authorization. however i'm looking for an elegant way or any bast practice to return data/resource belongs to specific user?
for example: I expect that http://localhost:3000/transactions will not return all transactions, only the transactions that belongs to the authenticated user that initiated the request.
my simple/manually solution? each transaction item has user_id field, so I can write middleware that decode the jwt token and takes the user_id from the token and expose it to the request object (i.e request.user_id = user_id from the token). and for each route (like transaction) i can take this request.user_id and add it to the query.
I wonder, what's is the best solution to handle this in express/node.js application? library? service? SaaS?

Your approach sounds correct. UserID is a value used for authorization, received in a digitally verifiable way, and referred to as a claim. A good approach is to design a claims or claimsPrincipal object containing details like this, used by your API's business authorization.
In Node.js this is sometimes processed in middleware when the token is validated and then saved to response.locals.claims, as in this code of mine. The values can then be used by business logic as you describe.

Related

Tracking multiple "Binance" orders for multiple users from a single connection

The task is as follows:
There is a list of users from Binance exchange, each user can create an order on the Binance exchange. It is necessary to implement a mechanism for tracking user orders on the Binance exchange through a single connection.
There are a lot of users. A lot of tokens and secret keys. One connection.
I use the node js library "binance-api-node".
But I am ready to hear any solutions to the problem.
Orders sent through the POST /api/v3/order endpoint (client.order() in the library) return a unique newClientOrderId (or you can specify your own and send it with the request payload). You can store it in your app in relation with the order and the user.
Orders that have been created using a different way (e.g. the Binance UI) are a little more complicated. You can receive the list of orders per API key, for example with the GET /api/v3/allOrders endpoint. Each order again contains a unique clientOrderId, and since you know the API key that you used to query these orders, you can make a relation between the clientOrderId and your user.
Note that each Binance account can have multiple API keys and there is no easy way to determine whether two API keys belong to the same Binance account or not. See this answer for more info.
Because each authenticated REST endpoint requires exactly one API key (and some endpoints also require exactly one corresponding secret key to sign the payload), it is not possible to communicate with the API on behalf of multiple API keys in a single connection.
You'll need to make a separate request for each of the API keys.

Should I use a custom JWT claim or query the db for authorization?

Let's say I have build a REST API for an application like WhatsApp and I got an endpoint like POST chats/groups/{group-id}/messages which adds a new chat message from my requestBody (This is just an example).
Before my API allow this request, it has to ensure that the request comes from a group member. So with that, I want to make sure that only group members are allowed to post new messages.
Since I didn't want to query the database for group membership, everytime I post a message to the group, I thought about adding custom claims to the JWT.
Could look like this
{
...
"groupMemberships": ["Some fancy UUID", "This one is a fancy UUID as well"],
...
}
With that I always could compare if the requester contains the target group in it's groupMembership array via the UUID. Sounds fine until now...
But what happens when the user is kicked out from the group ? Since the JWT is valid for e.g. 2 weeks, the requester could still send messages to the group, which is creepy and weird at the same time. A possible solution could be to blacklist the JWT but that's not really what I want, since that steals the stateless characteristic and lets me hit the DB anyway.
How could someone solve this problem ? Is it maybe okay to query the db for membership checks ?
One risk with your approach is that for some users the token might be quite big (what if you are part of many groups?). In general you want to keep your tokens small.
Another option is o let the API that receives the access token, do a lookup against your database as this is part of the authorization phase. By doing this, you can have long lived access tokens and the user can change groups as you like.
Alternatively, if you do add the claim to the token, you can then make the access token short lived, like 5 minutes, and have a long lived refresh token to renew and update the claims in the access token.

Protecting POST route without password possible?

Noob here working on first backend project.
What I’m trying to do...
Collect member data via my form (name, email)
User clicks paypal button to pay for membership
When payment approved by paypal, send post request with form data to my members endpoint to add new member
I now realize if I use postman to post to my members endpoint it works. So a malicious user could post data to my members endpoint regardless of paypals payment approval.
My understanding so far is that if my server allows CORS and I don’t password verify the user, anyone can post to that endpoint.
Is it possible to allow post requests only after payment approval without the use of a password?
I’m thinking of online stores that let you checkout without a password. How do they post the collected form data to their db without jeopardizing their post route?
Hope this wasn’t too vague. Pointers would be greatly appreciated!
I’m using node/express, but since it’s a general question I assume it doesn’t really matter..
These answers helped but still didn’t get me there.
Protecting post routes NodeJS
Can I only accept traffic from certain requesting domains with Expressjs?
So post / get request in general are functions of the browser and or server, I can create a simple html form and post to any URL I want to.. Now the question is, will it accept it or not.
When communicating between servers and web-services unless open to the public will use token based authentication to validate the request. So in terms of paypal, the typical flow would be.
(note, very oversimplification below and is just a sample of one such pattern)
User clicks paypal button from your site ( this will contain some type of paypal ID of sorts )
User is directed to paypal and after completing the transaction paypal redirects users back to your server with a token
your server reads the token ( sends API call to paypal with token to verify its valid, if success then process the post )
You can't prevent a user from posting data to a URL, however you can tell the server what to do if they do. So protecting your route from unauthorized post can be handled by sessions, tokens etc. For example, if you have a route on your server, lets call it user profile. This route first executes a check for the session, if its there keep processing, if its not, redirect the user.. Its really no different for callbacks / token auth.
Essentially, you will need to handle what the server does in your code because anyone can post to the endpoint.
To your other question about how companies handle guest checkouts, this can be done a few ways but one way is to create your own token, this token would be an encrypted string that may contain a cart ID, time etc.
When a user clicks 'checkout' the token is generated and passed to the server via a get or post request. From there your server decodes the token and if everything is correct processes the order otherwise it kicks it back.
Again, you see a lot of token based stuff here going on and that because there is an X factor in all of this.. the user.. We know who the server is but the user can be from anywhere and the user isn't a server so we need some way to maintain state between servers, hence tokens, encryption, JWT etc

How do i authenticate my api (node app) when being accessed by my UI?

I've looked at various approaches to this but I'm yet to find one that is perfect for my set up.
I have a UI that calls the api to present data to a user - the UI doesn't require someone to login and i don't want to authenticate every user. What i'm trying to do is simply protect the api because with the url to the api, anyone will be able to access the data.
In my mind, i can create a password/ apikey of some sort and store that as an environment variable that is sent from the UI to the API whenever a request is made. On the API, that apikey/password is validated before allowing access to the api.
Does this sound wise? Would you suggest something else? Have i missed anything. All thoughts are welcome.
The solution sounds good to me. You can do something like this:
back-end: create a new REST endpoint (something like /api/get-token) in your Node.JS application which generates a token (or ID), saves it locally (maybe into a DBMS) and returns it as response. Then, in every endpoint you need to protect, you extract the token from the request and, before sending any "private" data, you check if the supplied token is valid, or not.
front-end: as soon as your application is loaded, you send a request to the newly created REST endpoint and store the given token locally (localStorage should be fine). Then, every time the UI needs to access "private" data, you simply supply the claim within the request.
The implementation should be pretty straight forward.

How to implement server session validation scenario in MobileFirst 8?

I have a problem with the following scenario using MobileFirst HTTP javascript adapters:
let's say the adapters call 2 methods,
login, that calls a back end service which authenticates the user and also returns a customer_id (input: a username and a password).
retrieveData (protected by security-check) that retrieves sensitive data about a customer by calling a back end service (input: customer_id).
How can we make sure that some client that has credentials to authenticate and have access to retrieveData, will request only data that concern him and not be able to send a request sto retrieveData with a different customer_id from his own? (We assume that this client has tempered with the app and has made it send different customer_id's.)
With MobileFirst 7, after login was successful, we would call setActiveUser setting the returned customer_id as an atttribute of active user or we would call WL.Server.getClientRequest().getSession().setAttribute and again set the customer_id. So when a user called retrieveData, we would take his customer_id input and compare it to the customer_id in his session. If it was different, then they would get an error because they requested data that do not belong to them.
Since MobileFirst 8 does not have a session, how can we prevent this scenario from happening?
In 8.0, "Client Registration Data" is the closest thing to a session.
There are a lot of unknowns about your use case, but I will try to describe the expected behavior is most cases:
Assuming your security check extends UserAuthenticationSecurityCheck, as soon as the user succeeds to login, his user id will be registered in the client registration data on the server. This will map the client to the user in a database.
From that point on, on any adapter you can safely check who is the currently logged-in user by using securityContext.getAuthenticatedUser().
If you want to make sure that a client only accesses data it is allowed to, use this getAuthenticatedUser to check against your database that the requested data belongs to it.
If you really need to store extra custom data in the registration context (the closest thing to a session object) there are APIs in the security check to do so. See RegistrationContext.
In v8.0, the client is able to retrieve information from the backend system because it passed the challenge presented to it, and in return received an access token that enables it to access resources that are protected by a scope, which you define. This is how OAuth works more or less.
Have you read the Authentication Concepts tutorial? https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/authentication-and-security/

Resources