I have been doing some research about authentication and authorization on web api. I understand authentication (username/password) and ROLE based authorization, but what I'm confused about is authorization on data.
Say you have a user (user id 1) who is authenticated, an admin, and is associated to company ABC. I have other users associated to ABC which user id 1 can update. Now I want to update user id 2's name who is associated to ABC (which I should have access too). I need to pass in something to identify user 2, ie put /user/2 plus post data. I know on the server side that user 1 is allowed to update user 2 because he is authenticated and an admin.
Now I have user 100 who is associated to company XYZ. User 100 should not be able to update user 2. This is what I'm having a hard time finding information on.
What are some approaches/blogs/anything that can give some helpful ideas on how to prevent user 100 from accessing data outside it's company.
My thoughts are I could pass in the logged in users id (which I grab server side based on authentication) into the update stored procedure and do a check to make sure that user id is associated to the user being updated. To me this seems tedious and ugly in that every stored procedure needs a user id parameter and a check to make sure they can access the data they are accessing (maybe this is correct).
I know how to authenticate and how to check role based authorization, the missing part is resource based authorization.
Thanks for the help.
Does anyone have any insight. Its hard to believe that Role based Authorization is sufficient.
use the concept of authz where a user is prevented to see the details of other users
Related
i am making a set of applications that share a common oidc provider (in my control), where the users will be created.
One of my applications is a stateless SPA "meeting" app where you can schedule meetings with other users, and you login purely by an OIDC token.
I am having a hard time thinking a strategy about the following
Should the "user" details be stored in the meeting app after a login? So let's say user A exists in the provider, then enters the meeting app. Should i save user A in the meeting app DB?
How to handle change of user details? Let's say user A changes name to User B in the provider. Until he logs in again, all the other users see him as User A still in the "contacts" list. What is the usual practice for solving this?
How to handle deletions in the provider. I need someway to signal that "deleted in provider -> deleted in app". Should i constantly poll the provider and get any missing users, create a push system, or is this just unneeded?
Thanks a lot in advance
That's actually a very good question and rarely explained well in online articles. Hopefully the below detailed notes help you with your solution. I have answered your questions at the end.
OAUTH USER DATA
Typically the core user data such as name, email etc belongs in the Authorization Server. It contains Personally Identifiable Information (PII) and changes are audited there. This is explored in further detail in the Privacy and GDPR article.
DOMAIN SPECIFIC USER DATA
This might include fields like a user's application preferences, and you may end up with data similar to this in your APIs:
Field
Description
id
A database surrogate key for the user
subject
The subject claim from an OAuth access token, which is typically a GUID or something similar
archived
A boolean flag set to true when a user is active in the app
field 1
A domain specific value
field 2
A domain specific value
To get OAuth user data within your applications your APIs can call the Authorization Server's SCIM 2.0 endpoint as described in this User Management article.
AUTHORIZATION AND ROLES
Interestingly, roles and application specific rights could be stored in either of the above data sources. You may want to start by putting roles in the OAuth data, but for cases where they are very domain specific and change often, I have found that storing them in my own API data works best.
DOMAIN SPECIFIC USER DATA AND ACCESS TOKENS
Sometimes you need to include domain specific user data (which might include roles) in access tokens. This Claims Article explains how claims can be looked up from external APIs during token issuance. This typically involves a REST call from the Authorization Server to one or more APIs, providing the subject value for which tokens will be issued.
CONSISTENT USER IDENTITY IN YOUR APPS
A user can potentially authenticate in multiple ways, such as default password / corporate login / social login. You may need to use some custom Account Linking logic to ensure that the subject field in the access token gets the same value in all cases. This prevents you ever creating duplicate users within your application.
USER INFO CHANGES
These are typically made by end users within an application screen, and your APIs then call SCIM endpoints to update the core OAuth data. A common case is when a user changes their name and / or email, eg if the user gets married. Note that the subject value remains the same after this edit.
USER ADMINISTRATION
In scenarios where corporate assets are used, an administrator typically provisions users, either individually or in bulk. This can be done via the SCIM endpoint. In some cases administrator actions may need to save data to both data sources - eg to create a user and set roles + application preferences.
USER INFO EVENTS
Sometimes your application needs to know about a user info event, such as new, deleted or changed users. This can be managed via Event Listeners, where an extension to the Authorization Server calls back your domain specific APIs when a user edit occurs. When a user is deleted in the OAuth user data you might then update the user's application state to archived.
DATA MIGRATIONS
Finally it is worth mentioning that the above also supports migrating to an OAuth architecture or between providers:
Get a combined view of the user data before migration
Insert all existing users into the new OAuth system via SCIM
Update the combined view of the user data with new subject values
Update your domain specific data with new subject values
SUMMARY
So to answer your questions:
Aim to avoid this because it adds complexity, though in some cases you may need to denormalise for performance reasons. The OAuth user data should remain the source of truth and the only place where edits occur to PII data.
Your meeting app would need to join on the OAuth user data and domain specific user data and present a list. This would probably involve caching a combined view of the user data.
See Administrator Events above. Your API should be informed of OAuth user data changes via an event, then your SPA would get current data on the next refresh.
When implemented like this you end up with simple code and a well defined architecture. Some providers may not provide all of these features though, in which case you may need an alternative approach to some areas.
I am building a website using Node.JS/Express.JS that will allow a user to log in using a 3rd party provider (Discogs via OAuth1.0a).
I have successfully implemented the authentication process so that a user grants access to their Discogs account and I am returned an Access Token for future API calls. The Access Token does not expire. The user is classed by Discogs as an "authenticated application".
At the moment I am storing the Access Token in a session, which persists even when the user restarts the browser, or my server is restarted, so the user stays logged in. Great.
However, when I log the user out by destroying their session and they repeat the authentication process, the 3rd party provider treats the user as a newly authorised application, leaving the old authorised app behind. How can I get around this? Is it better to not destroy the user's session on log out and instead store the logged in state of the user? Discogs do not provide a method for de-authentication.
Also, there is some config to be set against a user once they are logged in. Should I created a dedicated DB table or equivalent for this, or would storing this in the session suffice? It seems like a dedicated user table may be superfluous as I am relying on the user's session id to identify them.
Generally, you will probably want to save some info about your users permanently on your own servers, so probably in a database.
In your specific case, that database should probably save some kind of unique user ID that you get from Discogs (do not save the access token itself for security reasons), which you can use on subsequent logins to identify which access tokens belong to the same user.
Your flow would probably be something like this:
User logs in via Discogs for the first time, you get an access token, put that in session
You figure out a unique user id somehow, you save that to your DB along with any other user info you might need
You put that ID in the session as well
User logs out, you destroy the session, but keep the info in your DB
User logs in via Discogs again, you get a different access token, put that in session
You figure out the unique user id, which matches the ID in your DB, so you write that ID into your session - now you can treat the user as the same user, just with a different access token
The unique user ID can be anything that is, you guessed it, unique. Might be an actual ID, a username or email address - I'm not familiar with Discogs but I'm sure you can figure something out and how to obtain it.
Let's think of a simple REST-based web service to store and retrieve JSON objects. Without any authentication, every user can access any data.
Now let's add usage of JWTs to authenticate users. Of course, since we are not doing authorization, still every user can access anything, but at least now we know who accesses what.
Next step: When storing an object, save the user's sub claim with the object, and verify that the user's sub claim matches the one of the requested object, and if so, deliver it. Now we have authorization on a per-user basis. So far, so easy.
Now let's add the possibility to let users share objects with other users. For the sake of simplicity, say, we want to have predefined groups (i.e., roles) and we want to let the user choose which group (role) has access to the objects they create. This is still easy, as you have a predefined list of groups, so you can let the user choose one or more, and attach them to the object. Additionally, the identity provider needs to be configured in a way that it put a groups claim into every user's token, so we can match them. As we can already see from the length of this paragraph, things become more complex.
Question 1: Am I right so far, that handling "static" groups this way it the way to go?
Now, let's give the users the opportunity to create groups on their own. This is still not complicated, but how do we make the identity provider use the dynamically created groups? For sure we do not want to make an administrator update the identity provider's configuration every day ;-).
Question 2: How do we handle dynamically created groups?
Now, finally, let's forget about groups, and let's say, that we want to allow the users to be able to simply share their objects with other users. This should be configurable for every object individually. How do we do this? Do we save a list of users on the object? If so, what exactly do we save? The sub claim? If so, how does the owner user know the appropriate values? Or ...?
And: Supposed the users want to put their friends dynamically into dynamically generated circles, how would we do that?
Question 3: How do tokens and dynamically created groups with dynamically assigned users work with each other?
In my opinion the tokens should only include identity-information(-claims) you'll need to identify the user on your ressource server or that wont change when refreshing, since you wouldn't want your user (or your app in place) to have to refresh his access tokens each and every time his permissions change (since access tokens grant access for a specific amount of time you wouldn't want your user to have access to certain ressources that he's lost the access rights to since his last token refresh by not refreshing the token and simply using the old one either). The more security related information you append to your token, the more vulnerability you may add to your system (depending on your token lifetime).
Stating so, I would (and always do) identify the users roles or groups by his user-id (which is included in the jwt-token) on the ressource server. To achieve this, I always attach the users identity-information to the current request on my ressource server and attach "dynamic"-claims like the users role or group to the identity.
By adding only the identity information I need to identify the user and the user's rights on my ressource server, I tend to use my identity providers across multiple applications without handling application scope on the identity provider, so I can use the exact same access token for multiple independent ressource servers.
Weblogic contains a lot of security providers. It's feasible to make more than one authentication provider active at a time. The problem is we need to assign a different role to the user whenever he is authenticated through one of the providers. Is it possible to assign a specific role to the user each time he got authenticated through one of the providers?
A user can only have a given set of roles at any given time. Roles can be changed in the admin console but can not be done dynamic and for good reason. One would not want an unauthorized user to be able to become the Admin to a server. You can assign all the roles the user requires but you cannot dynamically, using code, perform such compromising tasks.
In short, a user can only perform tasks to the ability that the role provides him at any given time.
I would simply like to ask if I'm doing the things right or if it is better if I stop before going in this direction. I have an administrative area in my website and I though to manage login using a table on my database.
When the user correctly login, I then write on a sql table the username, the session id and the IP obtained from REMOTE_ADDR server variable.
When the user ask for a private page that require to be logged in, I lookup the username on my table filtering by IP and Session ID, this return the user of the current user asking for example for "prices.aspx" page on my admin area.
I have then made my so saved records be deleted after 30 minutes. Is this safe enough? Is this a good way to expose my website to hacks? How could I improve the security?
If your site can be hacked, it doesn't matter how your login system works. What keeps a hacker from getting at your data?
Encrypted Transmissions
Never show database names, file names, passwords in front end code.
2 Step verification login to your website and database
The basic principles of logging a member in, or logging someone in to an authorized page are no different.
Whether you delete a record 30 minutes after it's been saved or not is totally immaterial. If a hacker can access that data, saving it in an unsecured manner for 1 second is to long. If you want the user session to time out after 30 minutes, just deleting the database record won't achieve that. So, to your question, "Is it safe enough?". No, it's not.
If your regular member login is safe, then all you need to do is have a field in your user information database, that indicates whether the user is authorized to see certain pages or not.
When your website is first loaded, don't ever load the admin pages unless it's requested, and then have the user give their password a second time. If the user who logged in is not authorized to see an admin page, then don't even load the HTML that allows a user to request an admin page.