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

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.

Related

express elegant way to restrict resources belongs to specific user

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.

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?

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 securely setExternalUserId() in OneSignal?

I'm setting up OneSignal on my website.
As far as I can see, there are 2 ways I can associate a push subscription with my user ID:
I can call OneSignal.getUserId(), which returns a UUID, and make an authenticated call to my web server to associate this UUID with my logged in user on my server
I can call setExternalUserId() to send the logged in user ID and associate it with the subscription on OneSignal servers
The first option is perfectly secure, as one could only hijack my client-side code to send an invalid subscription ID (or another valid subscription ID they have created), which is not a big deal.
The second option though, feels totally unsecure: anyone could hijack the client-side code to send any valid user ID and associate it with its subscription, and therefore receive notifications on behalf of another user.
Is there a way to securely use setExternalUserId() while preventing a user from associating their subscription with another user?
The only secure scenario I can think of is if my users had UUIDs as well, instead of sequential IDs, and these UUIDs were kept secret (i.e. never exposed publicly on the website).
Any other scenario I can think of sounds plain insecure.
Did I miss something?

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