Database user tables and permissions - database

I'm making a db system project for college that requires online log-in for people to read information on their payments. I have a "person" table that stores information on people, and they have a unique identifier that will be their user name, with the password being generated somewhere else (given how the system works, this part represents no problem at all). However, sometimes some people won't be directly involved in the data inside the database, and instead they will have a password granted to them that will be stored inside the database.
Now. How do I assign "roles" to these users stored inside the database? By the way I'm working with Oracle and JSP as my host language.

Well, you have to either
use Oracle's native support for roles,
store the data you need in a table, or
derive it from something you have available outside the database.
For native support, see, for example, docs.oracle.com for CREATE ROLE.
For storing the data you need in a table, you might be able to use something as simple as
create table user_roles (
user_id integer primary key references users (user_id),
user_role varchar(20) not null references user_roles (user_role)
);
If you do that, pay close attention to permissions on that table. You don't want users to be able to escalate their role.
For deriving it from something outside the database, you might be able to use something like
network login name,
IP address,
cookie, or
something else.
I'd be a little surprised if any of those work well, though. Most of them will probably require storing something in the database, too.
When I need roles within a database application, I usually rely on CREATE ROLE.

Related

Company Name? Claim? New Column?

I am planning to use Identity Server 4 and Asp.net Core Identity together. My website that will be talking to Identity Server 4/Asp.net Core Identity will be expecting that a company name comes back with each user.
Should I create a new customer table called Company and in the Asp User table add a column linking them together.
Or should this be a claim?
I know when I authenticated my user and they are sent back to my main site, I will have a company table and they will be linked but just not sure for the purposes of identifying them.
I feel like it should be a claim but I want to double check since I am new to all this.
In terms of using IdentityServer, technically everything is a claim. The "user" object IdentityServer returns will have all the properties mapped as claims. In that sense, it really doesn't matter which approach you go with.
However, it's generally better to keep data on your user table, if it makes sense to. Something like a foreign key relationship is especially valuable to exist at a database level, as there's more value to that than simply getting a company name.
Storing data as claims is most useful when that data is transient or not applicable to every user. Typical examples include things like third-party access tokens, such as from Facebook. Storing that on the database-level would inevitably result in denormalization of your database table, so it makes more sense to use a claim.

Database design: multiple users with different roles, extra field or separate table?

I'm modelling a database schema that has the requirement of including multi-user account functionality:
A multiple user account enables multiple users to login to the same
account in order to do the job according to their permission level.
This means that it is possible to maintain a single account for your
entire marketing team. The account owner can add as many users as
he/she wants and limit what permissions each of them has. You can
choose a role for each user: account manager, marketing executive,
marketing assistant, etc… or create a customized permission.
At the moment I have one users table that stores the information of a generic user with the username and password etc. How would one implement a multi-user account functionality? Could an extra field be added to the users table that simply indicates the role? Would a separate table be required? I would like to use the principle of keeping this simple where possible but don't know how to approach this.
Each user is a assigned to one group, is that correct? In that case, the user table can have a groupid which is a foreign key to a user_group table which lists all the access roles that you have.
Now the group (groupid) may have a number of "access rights" of what they can (or cannot) do on the system, which can be defined by you. You can refer to this as a default set of access rights.
If you want to create a customized permission, it's best to read this SO question / the first two answers in the least:
Best Practice for Designing User Roles and Permission System?
In the second example which discusses bitwise operators (if you are doing this custom, without help of a framework as discussed in the first answer), this is interesting assuming you understand the concept. Effectively you are summing up the decimal integers but they are being compared in binary to know what roles are granted for a given user. You can use this concept to also define what access rights each preset groupid has for predefined roles.
For Oracle we have "Virtual Private Database". For SQL Server / Azure we have "Row Level Security". Whichever RDBMS you are using, check for similar feature. It is most efficient for this scenario.

Securely store data for multiple party's in a single table

I'm certainly no DBA and only a beginner when it comes to software development, so any help is appreciated. What is the most secure structure for storing the data from multiple parties in one database? For instance if three people have access to the same tables, I want to make sure that each person can only see their data. Is it best to create a unique ID for each person and store that along with the data then query based on that ID? Are there other considerations I should take into account as well?
You are on the right track, but mapping the USER ID into the table is probably not what you want, because in practice many users have access to the corporations data. In those cases you would store "CorpID" as a column, or more generically "ContextID". But yes, to limit access to data, each row should be able to convey who the data is for, either directly (the row actually contains a reference to CorpID, UserID, ContextID or the like) or it can be inferred by joining to other tables that reference the qualifier.
In practice, these rules are enforced by a middle tier that queries the database, providing the user context in some way so that only the correct records are selected out of the database and ultimately presented to the user.
...three people have access to the same tables...
If these persons can query the tables directly through some query tool like toad then we have a serious problem. if not, that is like they access through some middle tier/service layer or so then #wagregg's solution above holds.
coming to the case when they have direct access rights then one approach is:
create database level user accounts for each of the users.
have another table with row level grant information. say your_table has a primary key column MY_PK_COL then the structure of the GRANTS_TABLE table would be like {USER_ID; MY_PK_COL} with MY_PK_COL a foreign key to your_table.
Remove all privileges of concerned users from your_table
Create a view. SELECT * FROM your_table WHERE user_id=getCurrentUserID();
give your users SELECT/INSERT/UPDATE rights on this view.
Most of the database systems (MySQL, Oracle, SQLServer) provide way to get current logged user. (the one used in the connection string). They also provide ways to restrict access to certain tables. now for your users the view will behave as a normal table. they will never know the difference.
a problem happens when there are too many users. provisioning a database level uer account to every one of them may turn difficult. but then DBMS like MsSQLServer can use windows authentication, there by reducing the user/creation problem.
In most of the scenarios the filter at middle tier approach is the best way. but there are times when security is paramount. Also a bug in the middle tier may allow malicious users to bypass the security. SQL injection is one thing to name. then you have to do what you have to do.
It sounds like you're talking about a multi-tenant architecture, but I can't tell for sure.
This SO answer has a summary of the issues, and links to an online article containing details about the trade-offs.

Authentication Database Fields

I am implementing an authentication system into an existing database system. Currently, the database has a "Person" table that includes things like: First Name, Last Name, Date of Birth, Email (username), etc. This is the primary table for a user.
I need to add the following fields for authentication: Password, IsLocked, LockDate, LastLoginDate.
Would you suggest putting these fields in the Person table or would you put them in a new Authentication table? My original plan was for "Person" to simply contain data about that person, not necessarily about authentication.
The other approach could be to store the password along with the email in Person, but then place the authentication data in a separate table. This way, the username and password would be in the same place, but the meta data would be in its own entity.
Anyone have any thoughts?
Thanks for the help!
Keep them separate so that users can query the system for information about a Person without necessarily having access to their account credentials.
This also has a nice side-effect where not all Person entities may have accounts.
Keep the account information separate. Your current business requirement may be for each person to have only one account, but it could come up in the future that a person needs to have multiple accounts, or even that you need an account that is shared by multiple people. Having a separate table for authentication means that such future changes will have a smaller impact on your code.
Also, from the perspective of protecting authentication information, the fewer people/processes that can access the account data the better off you'll be. It's much easier to implement table-level access than column-level access.
I don't think it makes much sense to create a seperate table for Authentication data. Authentication can't exist independently of the Person, as far as I can tell - and there doesn't seem to be a way one Person could reasonably be associated with two Authentications (or vice versa).
In other words: There's a 1:1 relationship between Person and Authentication, so why split it off?

Bring current user to the database layer

I have a classic 3-tier web application build with MySQL and Tomcat.
I want to save the creator id of each database record for all tables at creator_id column or just log it somewhere.
Current user is stored at the http session object.
Modify all queries and pass creator id parameter is unacceptable.
Can I solve the problem using triggers, alter table commands etc.?
What is the best way to do that?
PS. Hacks are acceptable and welcome.
The database can't possibly know which site user is sending the query, all it knows is which database user. And if it's a web application, it's probably the same database user all the time, no matter who is logged in on the website.
The short answer is that no, you're going to have to go with your "unacceptable" option, unless you want to create a database user for every site user, and have the site open the database connection using those, instead of one "shared" user. But that may end up causing more problems than it solves.
Based on what you say in your question, your logical application user ID is different than your database connection ID. IF that is the case how can the database possibly know what your logical application user ID is? unless you pass it in, there is no way for it to know who is doing what. You say that is is unacceptable to modify all queries to pass this in. However, you would only need to modify the saves where you want to record this "creator_id" value. You will need to modify those tables as well. Hopefully you have a table that contains all of these users and you can FK to the new column to this table.

Resources