We have about 200 routes in our application.
For each route, we check if the user has permission.
Therefore we have an express middleware that checks if the payload received contains either the value 1 (read) or 2 (write) for the user sending this request.
If the user has the permission or not, is stored inside our database and retrieved on login. From this point, it’s stored in the payload of our jwt token and send between front end and backend on every request which currently produces a pretty big overhead on each request.
My question is the following:
Is there a way, to check for these permissions, but not having those stored in the payload and not receiving them in our ‘hasAccess’ function from database every time a route is accessed.
I thought about getting all users permission periodically and storing them in an in memory database like ‘redis’ and then checking the redis store inside the ‘hasAccess’ way.
Is that a effective/performant/secure way to solve the issue? Is there another way that is common out in the wild?
Thanks in advance!
Related
I'm building my first 'bigger' web-app (only for learning purposes & my portfolio) with the vue.js-framework. I want to implement (for the fist ever time) the possibility to login using Google's API. My question is: where would I 'store' the user-obj? It should contain information like the user-id, name, email, ... . Would I store that obj in a Vuex store in my case? Or do I not even need to store such an object as the API provide all these information?
Well, it totally depends on the needs of your project and the information that is being stored.
If the information being returned in your user object doesn't contain any sensitive information that can be used by potential hijackers to steal other information then you could always store it in local storage, cookies or runtime variables in your code. Normally, vuex store is used for manipulating the local storage. This really helps when you are accessing the data from local storage via multiple components or nested components.
But if you have sensitive information being returned from the authentication authority, like the user id or user hash string then you might not want to store them in your local storage.
Additionally, you should only use this when:
You want to keep a track of user details even when the user closes and re-opens the browser
Passing the data set from one component to all other components is not really feasible
You need to keep the state of the data set synced in all components, so if it changes in one place, it will auto-reflect in the other place.
You need to frequently access the same dataset and it doesn't really change often, so as to avoid multiple api calls to back end server.
One scenario, I can think of is of the JWT token authentication. If you're not familiar with this approach, we usually authenticate the user and store his token in the local storage via vuex and all the api calls in all the components and views start using this same token as bearer token in the requests. When the token expires a new token is fetched and updated in local storage and the change is automatically reflected in all other places.
So it makes sense to check the needs of your project/code. If your project demands the use of the returned user object and it's safe to store it, please go ahead by all means!
I’m building a react native app that will interact with APIs that I also write/manage. I have found Auth0 documentation for implementing this flow, but I’m not sure on where/when to save the tokens. I want to be sure I nail this step, because I feel like it has the potential to reduce the security of the flow by a great deal if I don’t do it correctly.
Here is the flow as I understand it (no error handling, only happy-path for sake of brevity):
A user enters the app for the first time, or is not already logged in
They log in using the Auth0 web-login-thingy
I receive a token
I can use the token to authenticate with my API
Questions:
Do I store that token? I don’t want my users to have to log in every time they use the app. If I do store the token, where do I store it?
If I’m not storing it, what do I do? Do I ping an authentication/authorization endpoint with Auth0 every time they open the app and get a new token?
Say I am storing the tokens, if I'm using the ID token for user data, should I be hitting the API again regularly to keep it up to date? Only when the user opens the app again? Not until they trigger a change in the app?
Instead of using the ID token for user data, should I just use that to get the user's ID and ping my database for user data?
I have the basics of this flow, and I'm able to sandbox it, but I want to start applying production-ready app logic to this flow and that's where I'm stuck. I’m a little lost here, so any help is good help.
Thanks!!
Here's a brief answer to your questions when using Auth0:
Yes! you store it, the most secure way to store the token is in your device's local storage, that way it is not kept either in application's state or in a global variable.
2&3. See above, but to add more information, you can configure your tokens to have an expiry length. in theory you would convert this 'expiry time from inception' to a date object, and can do one of two things; you can request a new token using the Refresh Token (that comes with the original) once the expiry has been reached, or force the user to re-log in and re issue a new token at this time (i prefer the latter, prevents people from just renewing their tokens forever as long as they remain logged in)
Use the auth token to request user information after login, this can be stored in app state/global variables/wherever. You then want to use the auth token in the Authorization Header for each API call, along with whatever data you are sending. this ensures that even once someone is INSIDE the application, they need to have a valid token to actually do anything involving data (imagine someone back-dooring into your app and skipping the authorization, or using something like postman to just hammer your API with garbage). it would work something like this: GET userData { Header: auth token } -> GET userProfile (by sending your user ID returned from GET userData) PLUS {Header: auth token }
I can give more in depth examples if you wish, and i apologize if i misunderstood any of the question and gave redundant/incorrect answers
Edit: Resources about using secure storage for keys
Document for when to use in-memory storage Vs persistent storage. The TL;DR is use in-memory if the key is expected to expire before a standard session duration, and persistent for storing a key between sessions
https://hackernoon.com/mobile-api-security-techniques-682a5da4fe10
link to Keychain Services doc
https://developer.apple.com/documentation/security/keychain_services#//apple_ref/doc/uid/TP30000897-CH203-TP1
link to SharedPreferences doc
https://developer.android.com/reference/android/content/SharedPreferences.html
AsyncStorage is a simple, unencrypted, asynchronous, persistent,
key-value storage system that is global to the app. [1]
You could store it in your AsyncStorage, but thats not necessarily a secure location itself (e.g. not encrypted, accessible on rooted devices...). Typically clients will issue access tokens that last anywhere from several hours to a couple days and these will provide their owner access to your API-resources. If there is sensitive data behind your login screen, you're probably better off simply re-doing the auth-flow and invalidate older access tokens on login.
In the CQS pattern, the queries are responsible only for reading the database and not modifying the state. To create, update or delete objects in the database we use commands.
If I want to try login the user I need to send login and password to the server side. If the credentials are ok as a response I expect to get some userDto object. In a case when the client typed proper login but the wrong password I need to modify the state of the user object and increase the amount of failed login attempts.
In theory, the best option would be to send only one request to the database e.g. GetUserDataQuery
But if the query would modify the state of the user entity it means that we break the CQS separation rule.
The other option I see is to send a command first, called e.g. TryToLoginCommand and if the HTTP response is 200 then I can send a GetUserDataQuery. In such a case, we send 2 requests instead of one. But is this way 100% secure?
Maybe there is some other solution which I can not see?
And no in my case I can't use 3rd party service like Azure or Amazon for authentication and authorization.
Which way is the proper one, most secure and prevent brute force attacks?
Commands don’t have to be generated in response to user input. You submit the username/pw for validation on the server (I hope you’re not sending the users pw back to the front end for validation). The controller for that request issues the query necessary to validate the user. If the user is valid then the controller creates and executes the command to update what is necessary, then returns a success message to the UI. If login fails, again you execute a command to update what’s necessary, and return the num failed logins. It’s only one request from the UI, but runs a query and command on the server side.
While making an Login/SignUp RESTful API, should the response contain any other user information e.g. User Profile, Permissions etc?
When I've done this previously the Login returns a token for the new session and possibly the userid. Then I've had other services that I call with this token to get a list of permissions etc. You should make each resource do a single thing, which allows greater flexibility and reuse. Like everything though... this is my opinion on it but there is no right or wrong way to do it.
The REST principle is that when you POST a request to the server, it should respond with a status to indicate success or failure (i.e. 201 created) and a pointer to the new resource just created.
In my comments above the resource being created is the session and the token is the identifier of that resource.
I'm trying to wrap my head around restful API design on a bigger scale than one simple installation.
My setup would look something like his:
The question is, after a user has been authorized to do requests they get the access token. Should EVERY following request first go to the proxy, then to the auth server to check the token and finally get the data from the resource server?
Considering you need somewhere to store the users permissions/roles on what URIs he is allowed to use.
I was thinking if you move the tokens and the permission/roles to the rest proxy. Stored in a memory cache like Redis? And when a permission/role is updated on the auth server, it pushes those changes to the proxy. The proxy would not need to make additional calls to the auth server every single time reducing it to just 1 call to the resource server. Or maybe this is how everyone does it, two internal calls every request?
It is not a great idea to authenticate the token on every request. Instead , save the token in some fashion either in Redis or in a map on your resource server whose expiry time can be set in synch with the token expiry time.
Using Redis you can store these tokens along with the role against a single key say userId and set token's expiration time(by setting the expiry time of a key) .In this way once the token expires the calls will automatically be redirected to the authentication server on its own.
User roles and permissions should be saved on the resource server either as a separate set in Redis for maintaining permissions list to check against the user role which you will pick from Redis again (or depending on how you rest API facilitates setting permissions on resources as certain Rest API facilitators have inbuilt APIs for restricting resources via annotations). This permission list can be updated as and when modified.