How to handle REST API based on user role - node.js

I am creating a project that have two user roles, basic and partner users.
I have the end point /api/stores/:storeid/appointments
if the requester is basic user then this will send available appointments timings
if the requester is partner user then this will send requested appointments timings and should be able to modify them
keeping in mind each request has its own calculations and queries to send back data.
what i am thinking is to establish a new route like,
/api/partners/stores/:storeid/appointments
so i can process requests differently
is this a valid way of doing things or I should only have one route to the resource ?
then conditionally query and process the request

Related

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

Using invite endpoint to share with specific users

I'm trying to share a document in OneDrive by providing access to specific people across orgs. While I'm able to use the /invite endpoint to provide access, sometimes I am not aware whether a given email address is entitled to receive access. For instance, let's say:
A user from org-1 is sharing a file with three email IDs
Two email IDs belong to same org-1
But the third email ID belongs to org-2, which is not entitled to receive access as per org-1's policy
When I dispatch a request to /invite with the three email IDs, the whole request fails i.e. none receive access to the file.
Is it possible to have partial fulfilment? i.e. the entitled users of org-1 are given access but the user from org-2 is denied access, while the response returned is 200?
Also is this possible in Sharepoint as well?
No, you cannot make it partially success on the server side but you can validate if the given accounts are from your organization on your side(writing code) and then remove that and send the request. If you want to send it to other organizations as well you need to configure it on the tenant or site where you want to share data with.

How to handle multiple 0Auth Access tokens

I'm developing a system to get buyers data from a sales website and send it to the business' CRM as a contact, all through REST API using 0Auth 2.0 on both sides. So far so good, but the thing is multiple businesses could be using the server at the same time, so I would need to handle multiple access tokens.
I thought of maybe storing the access tokens, with the user id and the refresh tokens on an external database but I don't know how secure and efficient that would be, since it would need to query the user id every time it needs to get access to either API.
Is there a way to actually handle this in a more elegant way?

Organization on database with userId field in a microservice archecture

I have a question on micro-service architecture. example I have :
An authorization and authentication server which provide JWT (Keycloak for exemple)
2 micro service which communicate between them through REST.
1 micro service is a user service which create a new user in my database on each new user from the Keycloak (may be tomorrow we have Google or Github, it's important to take this in mind). When I'm creating a user I store his subject from claim in a specific field.
1 micro service which store the creatorId, the updateById for blog post for exemple.
Is it better to store in my creatorId and updatedById the subject (Like this I don't need to ask to my user service to identify who is a creator) or to store the userId from my user service and everytime call from my post-service which is the user that made the request (So I made Everytime a rest request to get the user which send the request by passing the JWT token to the user service).
IMO, sending Everytime a rest request will increase the load on the user service but a subject id for a different user can be the same for Google, Github and Keycloak.
I would do the following, so that you can move to a different Authorization Server (Google / Github) in future without too much impact:
User Service creates a row in its Users Table for each new user, with a database surrogate key as the main user id
This user id is saved to your creatorId / updateById fields
Meanwhile the OAuth Id / Sub claim is a column in the Users Table, but is not the main user identifier from business logic
The Posts Service can avoid calling the User Service on every single request if you cache claims in the Posts Service. Some resources of mine might give you some ideas that you can apply to your own solution:
User Management Blog Post
Claims Caching Blog Post
Claims Caching Code

Resources