I have a nodejs application + MongoDB, implemented authentication with jwt correctly! And all work fine.
My question is how I can allow only specific user for some resources.
I don’t talk about role like admin or guest.
For example 3 users are registered for my app,
user 1 login and get token, theoretically user 1 can get data from any protected data with rule “user”, even though these data is not related for him.
I mean user 1 theoretically can make request with valid token and looking for data about user 2.
So what the best way to validate if resource is related for specific user?
Related
I want to create a serveless login system with Discord OAuth. There are two ways I can think of doing this which are written below.
My questions are as follows: Am I barking up the wrong tree with these two potential methods? If either of the methods are suitable which would you go with? Is there a much better way of doing this?
User signs in with discord and an access token is provided
The access token is stored in a database along with the username and user ID
Session Cookie
The user is provided with a session cookie containing a user ID and session token. Each time the user needs to authenticate the session token is checked against the session token stored in the database - this requires calls to the database each time a user needs to authenticate which could potentially make things very slow.
JWT
The user is provided with a JSON web token every time a user needs to authenticate a serverless function is used to check that this token is valid and has not been tampered with - this comes with it's own security problems such as difficulty to implement token invalidation
How do companies handle authentication in their multi-tenant web apps?
Essentially I have a single PostgreSQL database instance with many tables. Each table has a workspace_id column which I will use to use to grant/deny access. You can think of a workspace as a client and a single user can be associated with multiple workspaces.
My initial thought was to:
Use the frontend app and let the user send the email and password to
the backend.
Backend validates details and returns all the workspaces the user belongs to.
The frontend app displays the workspaces.
User selects the workspace they want to login into. The id of the workspace and the user details that were passed in step 1 is again to the backend.
The backend validates again all the details and issues a jwt token containing the user details and the workspace id.
Later when the user tries to access any resource I will extract the workspace id from the token to check if the user has access to a resource or not.
I am halfway through implementing what I've described above but I am not sure if that's the best approach. What do you think?
I'm not sure I would call this multi-tenancy - really it is just a case of different users with different claims:
Users should log in once, then have access to the data that their user identity is entitled to
When your UI calls APIs, the back end should receive a JWT access token with either of these payloads. The second of these is preferred, but not all systems support that:
The user ID only
The user ID plus an array of workspace IDs
SIMPLEST OPTION
This might just be to look up the user's workspace IDs whenever an API request is received, based on the user ID in the JWT access token, as in Joe's comment above.
CLAIMS PRINCIPAL
If workspace IDs are used frequently for authorization across many API requests, then a better option is to design a Claims Principal object, containing data commonly used by the API for authorization, and containing the important IDs. It might look like this for a particular user:
{
sub: "wdvohjkerwt8",
userID: 234,
workspaceIDs: [2, 7, 19]
}
This object typically needs to be comprised of both Identity Data (stored by the Authorization Server) and also domain specific data. The above userID might be a database key, whereas the subject claim is often a generated value.
When an API request is received, you can either read all claims from the JWT access token, or combine domain specific data with the JWT data.
The Claims Principal is then injected where needed, so that your API authorization logic can be coded in a simple way. In your case this will involve filtering workspaces when working with collections, or denying access if the user specifically tries to access a workspace they are not entitled to.
Here is some sample Node.js code of mine that does this, using a region array claim:
Claims Principal Code
Authorizing Code
Doc
Good day friends,
I am developing an application, in my user system add the functionality for administrators to raise the level of the account (if level 10, it's admin) or ban it from the site.
Once the user logs in, he receives a token that contains information about the level of his account, whether it is banned or not.
This function works perfectly, but if the user is banned, they can continue using the site until they receive a new token or it has expired, since the information is acquired from the token. I want to force the user to close their session (destroy JWT token) once it is banned or its level has been edited.
I can verify in the routes that every time the user makes a call, the backend checks in the database if the user is banned or not. But I would like to simplify this step so that the server does not make so many calls to the database. It occurs to me to remove the user's specific token or make it invalid once it is banned from the site or its level has been altered. So the user is forced to log in again and get a new token.
Is there a method or library that makes it easy for me to remove the tokens or make them invalid?
Because if i enter with my admin account and try to edit my account and give it a level 1, i should not be able again to edit this user because my lvl is 1 and i need lvl 10 again for using this route functions, but i can edit it again because token authorization is valid and that shouldn't happen
I want to force the user to destroy their JWT token once it is banned or its level has been edited.
This is not possible, a user can retain any data you've given them.
The best solution you can get with tokens would be to have a very short expiry for their access tokens, and verify the blocked status and level every time you create a new one for them. If a few minutes of lag is acceptable to you, this is the way to go.
Is there a method or library that makes it easy for me to remove the tokens or make them invalid?
You are looking for plain HTTP sessions. You would not hand out any signed tokens with the data at all, you would store the session data on the server side - in ram, an extra cache, or a database. From there you can purge it to invalidate the session and log out the user, or change their access status.
There's a standard implementation for about every server ecosystem. Don't implement this yourself with a database request on every route, use a middleware solution like express-session (see How to use session variable with NodeJs?).
Let me first start by saying that I realize that this is very similar to many other questions about service access control but I can't seem to find one response that is relevant on all of the points below, so I am asking (possibly) again.
Some background:
I am building a web application with .NET that is protected by a custom forms authentication implementation. This same app (within the same domain) needs to leverage several REST services related to data management from within JavaScript/jQuery as many of the app's functions are not well suited to post back use in the forms.
I am trying to determine the most secure way to implement access control for the REST service based on the authentication done server side when the app was first accessed.
Here is an example use case for what I am describing:
user logs into asp.net site using forms authentication and upon successful authentication the user is taken to the landing page of the application
the user chooses to access a page at ~/Users.aspx from a link on the landing page, which forms auth allows based on the cookie created by the authentication in step 1
users.aspx loads some basic HTML elements, like an empty table and a hidden field that contains a token (GUID) generated at page load. The token in the hidden field is used by JavaScript to access a REST service that retrieves data to populate the table. The token is stored in a database with a pre-defined expiration.
when the REST service is called with the token it is checked for expiration and used to determine the user making the call and provide authorization to the data being accessed from the database, if the user is authorized to access/update the data the service performs the requested service operation, extends the expiration on the token, and returns a response.
I know that the token would be visible to someone sniffing the request/response on the network unless SSL is used to encrypt the transmission, so SSL is used to counter this.
My question is:
Are there other attacks that the service would be vulnerable to?
is there a better way to handle authorization and user identification for the REST service based on the server side login other than a statically assigned token for the service? It seems to me that the statically assigned user token would be less secure since it would give endless access to the service if it were obtained by a malicious user.
assuming the answer to #2 is no, is there a better way to transmit the token to the client and store it there for the life of the page use knowing that it needs to be accessible from JavaScript/jQuery?
I'm building an application to send cart to my trello board, but I don't want for users to accept application (for this they must have trello account) instead I created another account ('slave account') and give it read,write permission to my board and generate read,write token that never expires.
On my webpage I include core.js
https://api.trello.com/1/client.js?key=[appkey]&token=[token]
Everything works but... if user checks my code he can see my "app key" and "token".
So my question is:
1. Is this a security problem - visitor can take this app key/token and access bord? (I believe it is)
2. How do I change my code so that visitor of the page doesn't see my app key/token?
thx
If you are making you token available to people, then yes, there is a potential security issue there - with the key and token, they can issue requests as you for any permissions you have granted on that token. So if you want to create a token with write access to the board, you probably want to keep that on the server side, and have your Javascript submit to your server, which then in turn relays that to the Trello site using the token you generated.
If you are worried that you have revealed a token you did not want to, you can invalidate it at the bottom of your account page at https://trello.com/your/account.