I have a simple .NET 3.5 app for changing some database fields using an ODBCDataSet. Now the Feature Creep is asking if I can hide or show tabs and other controls based on the user's database permissions.
Ideally, I would like to control the permissions only on the SQL Server using Windows user groups, and the app would not have any built-in authentication or permission system--it simply uses the logged-in user's Windows account for the database connection. So thus it would have to "test" the permissions to determine whether or not to show the tabs for the user. For example, if they have "write" permissions to a certain table, then the tab for editing it would be visible; if not, the tab never loads for them.
That's really the part I need help with: how can I list or test the user's permissions to the ODBCDataSet?
Are you opposed to having your app aware of the Windows user groups? Generally we use AD groups all the time for security like you speak of on both the database AND in the .NET code. Showing/hiding features is exactly the point. Additionally, even if for some reason they manage to get the feature to show, the database additionally checks their role and can prevent actions.
Personally, I think checking the role membership in .NET code is the easiest solution (you can do this with the IsInRole method).
However, if there are reasons why you cannot or do not want to have the app aware of group names, in case they change, I understand. There's probably not an ODBC method of checking, as any method would most likely be proprietary and/or database dependent (SQL Server, etc.)... other than that, you'd have to write code to attempt an insert/update command on a known test record and see if it comes back with an SqlException I guess.
You could always Try/Catch the call to the DB. This would authenticate the user to the DB, then create a Stored Procedure to return all tables accessible.
Related
We have an application (C# on the server, using AngularJS / Web Apis for a single page application) that assigns users different roles, which are stored in the database. When the user logs in, the user object (including RoleID's and RoleName) is transformed into a JWT and sent to the user, which is then used as authentication.
We're having trouble determining the best way to maintain and use these access roles however. Specifically, to use them in the current set up, it would seem that we have to hard code either the name of the role or the ID into the application.
For example, on the client side, if we want only users with a Manager role to be able to see and click a button, we would have to explicitly state that, ie if (UserService.HasRole('Manager')) { doStuff(); }.
Conversely, we'd have to do the same thing on the server side (because everyone knows relying on client-side security is bad). When the server gets a request on the API, it checks the JWT for validity and, if valid, checks the User's roll to see if they are allowed access to the specific web API endpoint.
This all seems prone to breaking if a role is renamed, or the ID changes. I generally hate hardcoding things like this. Is there a better methodology or approach that can be taken here?
In the past, when we've done RBAC (Role Based Access Control), we decouple the Role from the Permission e.g.
Role Permission
===============================
Manager Create Order
Manager Delete Order
Till Operative Create Order
Administrator Create User
Administrator Suspend User
etc.
This could be stored in a database and cached in something like Redis. Two tables, Role and Permission, where the Permissions need to match the ones built into the application (you could script this).
So your permissions grow with your application e.g. you add a new dining service, you can add a "seat diners" permission. The permissions for existing/mature bits of the software should rarely change (unless they were written incorrectly), whereas the roles are entirely fluid and can be renamed etc.
You can then use an annotation/security framework to ensure that the user making each API call on the server side has the correct role required.
You can even make it additive and allow a user to occupy multiple roles at once to blend things together.
You may maintain your user to role mapping in the database also in another table (using FK constraints) or you may use something like LDAP with the mapping being looked up from the DB/cache.
On the server side, Microsoft has built in management for roles. I would first look at
http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity
And then I'd also look at the the IdentityServer project for working with JSON Tokens on the server side.
https://brockallen.com/2013/04/14/getting-json-web-tokens-jwts-from-adfs-via-thinktecture-identityservers-adfs-integration/
On the client, I would suggest storing the tokens as either just in memory javascript or if you want them to persist, I would store them as cookies but make sure to set the cookies to not be accessible by JavaScript by using the httponly parameter when creating the cookie.
HTH's
Background
I'm building a single tier application Winforms application using C#. A SQL Server localdb database is attached to the application that runs when the application does. The plan was to use Windows Authentication to verify that the user is part of the MyApplication role/group and can use the application. But, in order to prevent users from accessing the database via other means, I was thinking of using an Application Role so that only the one SQL application user can edit the db tables.
Question
My understanding is that in order to use an Application Role, you need to provide a username and password in the connection string. I can encrypt this information, but obviously it will need decoded before being sent to the database. Is this a concern in a single tier application? What are other alternatives?
To use an application Role, you'll use the sp_setapprole stored procedure where you will provide the name of the application role and the password, rather than sending it in the connection string. When you use application roles, you still connect using an ordinary login, but once you successfully sp_setapprole, your connection loses its user permissions and instead gains the permissions of the application role. Having the decoded password in memory is a concern if you have reason to believe that users may decide to use a debugger to attach to your process to extract the password. Any administrator would also be able to decrypt the encrypted password on disk as well if you choose to use windows machine-level key containers. Using only a single tier for an application that uses a database is a security risk, and you have to decide based on the circumstances surrounding the application whether it is an acceptable risk to gain the reward of skipping a few weeks of design and development.
Source:
https://technet.microsoft.com/en-us/library/ms190998(v=sql.110).aspx
I highly recommend implementing a web api to manage your application's interactions with the database as well as security. This web api could use a windows "service" account to authenticate with the database, and users would authenticate with the api using their individual windows accounts. This has the added benefit of you never having to think about passwords. As far as managing API permissions, that is an issue that is up to you to design and implement as you see fit. The main issue you need to understand and deal with is uniquely identifying AD users. Take a look at this SO post for more info on that: What Active Directory field do I use to uniquely identify a user?
Your service account would have all necessary permissions on the database to do what the application needs to do, but not all api users would necessarily have permission to use all api functions. You would manage a store of uniquely identified AD users that have permission to use the application and what permissions they have. The rest is design and implementation details that are up to you.
Define user with privilege only to execute stored procedures. By this way if someone use SQL Management Studio, s/he cannot browse/edit tables and even cannot see the table names.
I have a Windows application project that uses SQL Server 2012 for maintaining it's data.
For securing my app, I decided to create a SQL Server login for every user in my system.
Is this a good idea?
If you're not using Windows Authentication then this will be your best bet. You could also place Users into Roles and specify permissions for that User group.
If you require that each user has different permissions and you you need to be precise as to which user has what permissions to each database entity (table, view, stored procedure, function etc) then creating a new user will be the way to go. This will allow to you fine tune each account,enable/disable accounts, grant/revoke permissions easily.
As #dash states it will be harder to maintain, but I think having the granular level of security outweighs maintaining a large number base.
You could try creating an access matrix table to map data access levels to each user. Then, you can show/hide the data loaded in your application depending on the access level of the signed-in user. As #dash said, this will be harder to maintain but it may well be an easier option than creating individual logins. Secondly, I suppose it would also be easier to create an insert/update/delete script to edit the matrix rather than have a DBA edit the SQL Server logins.
I have written some C# which connects to a live production database. I want to give my application read only access to the DB but am unsure how to achieve this.
Is there any trivial way to get this done by amending the connection string?
My understanding is that the application will logon with the credentials of the person running the application and hence may or may not have write access to the db based on that fact. Can I statically limit the permissions of the application so that if someone changes the program to do something devastating at a later date any manipulation will fail?
Apologies for how trivial the question may be but it's my first venture into the world of MS programming.
Thanks,
Gav
You can't change the permissions for the account by changing the connection string. There is a user account in the database that determines the permissions.
Unless you want different people to have different permissions, you should set up an account for the application and use in the connection string.
For any account in the database you can specify which databases it can access, and what it can do with the databases. The permissions can be specified down to the level of objects and operations, so you can for example specify that it can only do selects on certain tables.
Have it login to the database server as a user that only has read-only permissions. That and just don't try to write anything to the database.
You can always grant the user connection to your database just the "db_datareader" role on that database.
db_datareader gives your user SELECT permission on all tables - but nothing more.
There are basically two main types of SQL Server authentication:
Integrated Windows authentication and
Mixed authentication mode (SQL Server authentication)
It sounds like you are using the former. If you use the latter you can create a specific user account within SQL Server, give it a username and password, and then grant access to the tables you wish it to be able to read. You can control at the account level what access it has to any object in the database.
See http://msdn.microsoft.com/en-us/library/ms144284.aspx for more details.
Just a thought; usually not every logged in user gets to access the database, let alone a read-right. Therefore you in your case you can create a database user for your application with read rights; and use that in your connection string.
I am building a C# app which will need to talk to a database - I have written a module which checks whether users are permissioned appropriately and then uses a shared username to run the query
This means that permissioning is done in C#.
I am now wondering whether this is a good idea and whether permissions should be applied a the database level ie each user set up with their own user name and account. The reason for NOT doing this is that we are not DBAs and getting users added
What are the benefits and problems of permissioning users at the database level rather then c# level?
I always use a database login/user set up for my application.
By doing this i can operate reasonably safely within a database that may be shared with other applications - my application can be granted just the permissions it needs on the objects it needs to access.
This decouples the users from the database - it means that user Jane Doe doesn't need to be given specific rights on the database to use my application, which DBAs love as because of that it also means she can't just start up SQL Management Studio and start looking through tables (because she has no rights).
Edit: note that it is not necessary to give each user a login in order to audit who made changes - my app can still be logged in as one (restricted) user and i can pass the machine/user name of the user in to whatever stored proc i am calling so that data changes can be logged.
You can certainly have a group set up on your database and allocate the correct permissions to this group, but that means you then have to add/remove users from that group as necessary, which can be an administrative annoyance.
How important is the data in your database? Is auditability (logging who changed the data, what they changed and when) important?
If all your C# program does is read the data and the data is public anyway, then what you are doing is fine. This is exactly what happens on a website where users do not need to login, all queries are run from the same user.
For a high security, mission critical application rolling your own security in the code is seldom a good idea, much better to utilize the security system built into the operating system.
Are your computers part of a domain and do you use Active Directory? If so, you might want to consider using Windows authentication and groups.