(ASP.NET MVC 4.5) Imagine you have a model for a bank or a company that has IDs that are sensitive information such as an account number or some other personally identifying information. What is the best way, or at the least what are some strategies, to route the edit/display actions without placing this information in the URL.
Obviously this would be bad:
https://goliath-natinal.com/Accounts/Edit/954321
if 954321 is your bank account number.
I imagine one way of doing this would be to add a GUID to each account that acts a a surrogate key. But I'm very curious to know if there are any possibilities for doing something if you cannot change the database at all.
Just throwing some ideas out here...
You could encrypt your identifier using Rijndael or some other type of encryption. You could salt and hash it based on other identifying fields related to the account. You could do that on the fly. You'd take a processing hit though.
If you're using a memcache or azure caching you could create a map of accounts to guids and let that just sit in the cache. If allowed, in the DB you could create a separate mapping table that maps the account to a new guid.
Can you give more info on the full restrictions? I.E. Is the table restricted from change, or the whole DB? Could you create a new DB?
Related
I am fairly new to coding in the .Net environment. I am having trouble finding "real-world" examples on authentication/authorization using Identity. Most examples I come across are primarily textbook examples that use the ASP .Net registration template.
I am trying to find guidance on where to look (yes, I Googled and I get very unrealistic/unusable use cases or "classroom" examples) or how to do this.
I work for a small school and I am trying to build an application (possibly Blazor - just experimenting with various technologies now) that allows both students and employees to login into a portal and view their relevant data. I have an Employee table and a Student table based on POCO classes. When I add identity to the project it creates Users and Roles tables as well.
I would like to have the "Users" table based on the Student and Employee tables - not have a separate users table. I do not want to have a "registration" option either. I would like the option for an Admin (which would fall under an "Employee") to be able to add users, but not use a registration page.
How would I implement Identity and Roles without using all the extras added? I am using .Net 5.0.
Thank you for your time and pelase forgive the English - it's new to me as well.
I understand what you're trying to do. It IS possible to Create a Custom AuthenticationStateProvider
But unless you have a VERY robust database already, I wouldn't do it. Getting the default system set up and migrating users will take at most an hour. Setting up your own custom authorization system is likely to take you MUCH MUCH longer.
Having different users in different tables is not a good design plan. They all have names, phone numbers, e-mails and so on-- put them on one table.
Hi Derrick and welcome to the community! #Bennyboy1973 is correct, in that both your Students and Employees are all "Users", so they should all be stored in the same table. To add to that response a bit, probably the simplest way for you to manage them is by using Roles, so the Students could be in one role and the Employees could be in another. By having a role attached to each, you can then use the roles as a filter in your queries and you could also restrict the access and actions each type will have based on the role they are in.
Regarding having administrators add the users to the database without public access, this can be done as well. Once you get the default identity system up and running, you can scaffold out the whole system so it can be modified, and probably the easiest way to achieve what you are after is to then modify the default registration (signup) page so that it requires the user to be authenticated to reach it, and then implement a confirmation email to activate each new account.
There are a few things with this approach that you need to be aware of as well.
Since the admin will be setting up all the other user accounts, you should modify the email confirmation chain to require a password reset at some point. The administrators can have access to the user's information as needed but shouldn't have the user's passwords.
Identity Server will store passwords in an encrypted format, and you'll need an initial user in your database. What this means is that you will have to "seed" an initial admin user into the database that you can use to sign in and get started with everything else. You'll have to research how to do this, as it isn't as simple as just accessing the database directly and adding the user and roles because of the encryption. The program you build should be designed to do this for you on either the first run or if you are connecting to a new database, using a username and password that you know. It will then store the user properly that you can use to sign in as Admin, then change the admin password. This makes the whole thing more secure.
This all sounds like a headache, but it's worth it to work through and know how it all fits together. The, as mentioned in other answers, you can migrate existing data into the database.
I have a shared Database for a Multi-Tenant WebApplication, that uses Entity Framework Core. The Tenants have their own Tenant Table and every model has a Tenant ID.
By Design it is not possible to access the data of another Tenant because I have Query Filters and the code in the controllers always checks TenantId.
But I would like to encrypt the data of each Tenant or at least the most sensetive data with a different key or purpose string.
I implemented it for one model with the Protection API.
It would be a lot of work though to implement it for every model, because I have to call protect and unprotect after every Database call in the controller.
I am using MariaDB as my Database. Does somebody know if it is possible to let MariaDB do the encrypting? I know you can encrypt the data at rest, but is it also possible to encrypt different rows identified by TenantId with a different key?
I am creating a Web API service for an application with a single tenant database. Each company will have it's own database strictly controlled and created by us. I am aware of the maintenance implications of single-tenant databases compared to multi-tenant and we feel single-tenant best fits our needs. Users will be created by us only.
There will be a master database to "map" each user to their company database when authenticating based on only their username (email address). If there is a match on email the authentication will then continue within the client's company database which will contain the password hash.
This leaves the databases self contained which is needed for foreign keys for audit records. The master database simply acts as a mapping or routing based on username (email address).
I created a new Web API project and used the Individual Accounts template. I like the way it works but unfortunately I don't see how I can customize this enough to accommodate for my needs. Would this be possible? I need to use tokens. The only other alternative I can think of is a completely custom authentication procedure but security is not something I want to take lightly as I'm sure I will mess up somewhere along the line. I am aware that the user passes its username and password over SSL to the server which responds with a token which then gets included in the header of each subsequent request to an authorized resource. I just need to know if this is something I will have to completely implement myself? This whole thing may just be a silly model for an application in which case I am open to suggestions.
Any feedback would be helpful.
Thanks
After lots of searching I finally found the type of solution I was looking for. Dominick from Thinktecture has a blog post which details a nice embedded token authorization method which I can now extend upon. This is exactly the type of solution I was looking for as it is extremely simple.
Embedding a simple Username/Password Authorization Server in Web API v2
I'm new to Redis and was hoping for a "best practice" solution to implementing the equivalent of a "users" table in a mysql database, for handling users in a web app.
Would I create a users SET in Redis? Or a users database with a SET for each user?
My standard setup for users is a serialized object in a standard key u:userid - this object gets retrieved on each request, and there is never any need to access only one of the properties.
You could also use a hash rather than json for the user properties, but my setup includes everything getting used as strongly typed objects and redis running on a different server from the client, so using json makes it easier to use generic deserialization and minimizes any latency issues.
In addition to the user object itself, you will need an index for any fields you need to use to find a user - for example to allow a user to log in with email address you will need a key e:email => userid. A hash will also work here - the important thing is that you need something that is O(1) to get from an email to a user object.
Sometimes parts of the user data should have their own keys - for example a followers list is a perfect match to a redis set, so is best stored in that form.
It really depends on what you'd want to do with the Users within your application. Another option would be to have each user be it's own hash, where they keys are properties (fields) for each user (firstName, lastName, etc). You could use a key that you increment as the ID generator for inserting, and potentially another set that you use to hold all of the user IDs.
I have an ASP.NET MVC application where I need to allow to customers configure MembershipProviders based on their environment, but still be able to map that MembershipUser to a concrete User model in our database.
Membership.GetUser() will give me access to the logged-in user's Membership.ProviderUserKey. I can use this to relate to a User record. Our custom SQL provider will just return the User.Id, but AD is a different story. In that case, ProviderUserKey is an IdentityReference.
These lookups will happen very frequently, as you can imagine (although caching can assist in reducing the lookups at the database level).
I can't decide which route is better to go: Storing the SID as a varbinary or varchar column. This column would not be a primary key and would not have a clustered index. Knowing that I can index strings pretty well, and reading a SID in string format is certainly nicer than binary. Anyone willing to share how they solved such a situation?
Update
I don't know how I missed this SO question when I was searching before I posted, but it seems pretty clear that ActiveDirectoryMembershipProvider and ActiveDirectoryMembershipUser are not quite cut out for the task at hand, as they exist today.
An answer in that SO question linked the following article, where the following was stated:
The relative identifier portion of a
SID is unique relative to the domain,
so if the domain changes, the relative
identifier also changes.
Thus when a User object moves from one
domain to another, a new SID must be
generated for the user account and
stored in the Object-SID property.
However, each group and user has an Object-GUID, which will never change, even if the account is moved. Therefore, it would behoove me to use Object-GUID in my User class, and not Object-SID. Otherwise, someone's User record will be abandoned if they are moved and therefore breaking the relationship between their principal and the data they created.
Unfortunately, ActiveDirectoryMembershipUser doesn't let me get at Object-GUID. So, I'll either have to translate the SID to a GUID after ActiveDirectoryMembershipUser does its work, or create my own MembershipProvider that does everything I need on the spot. Unfortunately, this means I might have to duplicate effort already done for me by ActiveDirectoryMembershipProvider.
Microsoft stores SIDs as varbinary(85) in sys.server_principals
This is also a unique column, so it must have an index...
username is the LAST thing you want to index on.
SIDs only change in an AD when you change a user from one domain to another. RIDs are split into 2 groups - inbuilt (< 1000) and user RIDs. Pre-defined users such as Administrator, Guest etc always have the same RID.
If you want to handle movement of users etc, then GUID is the way to go.
username can be changed at any time in Users and Groups management.
this is different to the object name, which is invariant, but I don't believe is mandated unique across a forest. You can have any number of John Smith users.
I'd look into the ADSI objects. These are COM objects which should be accessible from ASP. MSDN explains pretty well. an ADSearch object can be used to return user attributes (e.g. including DN) from a GUID.
Sounds like you're making this a lot more difficult than it needs to be. What do you need a SID or GUID for? You already have a unique, perfectly readable identifier for the users account maintained in ActiveDirectory.
It's called "the username". Hopefully it's the same username as stored in your apps "user" table.
Your app just needs to know if that username successfully authenticated with ActiveDirectory. So if they successfully log in - you just store the fact that they are authenticated in your Session variables.
If they are configured to use the db user login, if successful set the same Session variable indicating that they successfully logged in.
No fancy GUIDs or SIDs ... simple.