I am very new to Spring security and my problem is as follows:
I have a member mysql table that contains information about the website's members, including their usernames, passwords and roles. So far so good: I can use this table to configure a <jdbc-user-service.
However I also want to have a super user that is not going to be in the member table.
Is it possible and recommended to have this super-user in an in-memory user repository and therefore mix jdbc user service with in-memory user service? If so how?
If 1. is not possible perhaps I can have a second mysql table called for instance moderator. Then what sort of sql query would I need to authenticate against these two tables?
Collissions
The problem with multiple repositories is that you need to ensure that you differentiate which user is which. For example assume your data looks like the following
member table
username
----------------------
member
moderator table
username
----------------------
moderator
Then you have some data associated to your users
data table
username value
----------------------------------------
moderator secret
What now happens if you get a collision? For example, a user signs up and your member table now looks like this:
member table
username
----------------------
member
moderator
Which moderator owns the data? There is no way to distinguish between the two users.
Alternative Approach
The alternative approach would be to use a mapping of users to roles. It would be to use something like this:
member table
username is_moderator
----------------------
member false
moderator true
Then when a user tries to sign up for with an existing username, there is a constraint violation so you do not need to differentiate between the two. Of course you could map the roles using another table. This is what Spring Security does normally using the authorities table.
Using multiple UserDetailsService
If you really want to use multiple user repositories anyways, you can simply declare multiple UserDetailsService entries in your configuration. An in memory configuration example is shown below:
<authentication-manager>
<authentication-provider>
<jdbc-user-service .. />
</authentication-provider>
<authentication-provider>
<user-service>
<user username="moderator"
password="password"
authorities="ROLE_MODERATOR"/>
</user-service>
</authentication-provider>
</authentication-manager>
If you want to do both in the database, you need to determine what your SQL queries for each table are and then add two elements. For example:
<authentication-manager>
<authentication-provider>
<jdbc-user-service .. />
</authentication-provider>
<authentication-provider>
<jdbc-user-service .. />
</authentication-provider>
</authentication-manager>
Use the attributes to control your sql queries. You can refer to the Spring Security appendix for example queries.
Related
My DB has following tables:
Resource: Some resources can be uploaded on site
Groups: Groups on site
Users: Users on site (not necessarily be part of any group but could be if they like)
Now, when some one uploads a resource then currently, ownership of that resource is given to it's uploader by default. So resource table has column OwnerID with foreign key association to User table.
But now, this has to be changed such that ownership of a resource could be given to either a user or entire group.
I'm trying to decide the migration scheme, to move this owner being user to an entity that could be either user or group. Intuition is that when someone uploads a material, he can choose its owner to be a user or entire group.
Currently my migration plans involves:
Add OwnerType (User, Group, Global) and UserOwner and GroupOwner within the Material table (probably worse normalized table).
OwnerType could be Global if owner is everyone --or-- Group if owner is group entity else user.
Then when I'm querying the Resource table, I can check the OwnerType to condionally select its Owner from either user table or group table.
I do not know if this is good way. I'm using entity framework, and things are already started to look ugly as User and Group hardly have any relationaship that would require me to make generalized entity.
Can some expert guide me on this? What is generally considered good migration plan in this case? Thanks for any help or suggestions.
I am implementing a multiple login system, using Facebook, Twitter, Email.
If the user login with Facebook, he is able to merge his account with Twitter account or Email account, so next time login, he can press on "Login with Twitter" or key in email+password to login.
Now the problem is the merging.
If user created account A using Facebook login, modify some data, then create account B using Twitter login, and modify some data, this would be hard to merge, because both accounts will have different data.
What do app/site who use multiple login handle this kind of situation? Or is it me who makes it complicated?
I guess the main point is not storing any detailed account information with the login method. This is probably what your user account DB looks like now:
- account_id: …
facebook_auth_info: …
username: …
birth_date: …
- account_id: …
twitter_auth_info: …
username: …
birth_date: …
Now this schema should make it a no-op to “merge accounts”:
- account_id: …
facebook_auth_info: …
twitter_auth_info: …
username: …
birth_date: …
In other words, treat Facebook, Twitter and other as a “identity providers” and allow for multiple identity providers per your own account.
The way I would do this is to keep separated third party login details and use tables like email and third party login details interchangeable to authenticate a user. This way you can have a customer that get authorized either by using email or using a third party login. This does not mean that the same user can login either with email&password or third party provider. This I find it helpful to avoid having all the time fields for third party providers in the User table and if you want to add more login providers you don't have to alter any table, just add another entry in Types table.
For example I would use a Users table where you you keep all details for a customer but login details. No email, password or any other login details. These details are held in separate tables and are linked by the PK from this table. This table will map 1:1 to the Emails table. For example a schema might be:
- Id (PK)
- FirstName
- SecondName
- etc.
Then I'll have an Emails table where I would keep the email and password for a user. You can also have extra details like Id and Verified (to know if email is verified). Please be aware of keeping plain text passwords or keeping pairs email - password in your db. This is an important security concern and I would not discuss it here. I would also use a UserId column to map emails to users. This will map 1:1 to Users table. A schema might be:
- Id (PK)
- Email
- Password
- UserId (FK)
- Verified
To handle the third party login details I'll use a table called ThirdPartyUsers. In this table I will store a UserId to map one record from this table to one record from User tables. Basically this table can replace Email table and you can move away from holding email - password in your db. In this table I would keep a ProviderCode that is a code from types table and a ProviderId that is an Id provided by third party logins. This Ids are unique per third party providers and don't change per user. You can pair a ProviderCode with a ProviderId to make a composite key. This will map 1:1 to Users table. A schema might be:
- Id (PK)
- UserId (FK)
- ProviderCode
- ProviderId
To have a unified User account I would have a MasterUsers table where you define a User as a Master user and you define into a link table its children. Through its children I understand any account that has the same email address. This means a classic account and any third party login providers. Using this you can a unique Master and multiple children. This would map 1:1 to Users table and 1:* to MasterLinkToChildren table. A schema might be :
- Id (PK)
- UserId
To link multiple customers to one MasterUser I would use a link table called MasterLinkToChildren (or any naming you prefer). In this I would have two columns for storing UserIds for childrens and MasterId for their parent. An important thing I would do is to make any MasterUser also be a children of himself in the Link table so when you update the MasterUser you would keep consistency between your records. This will map *:1 to MasterUsers and 1:1 to Users table. A schema might be:
- MasterId (FK)
- UserId (FK)
Finally I would have a Codes table where I would store unique code for each third party login provider. This would map 1:* to ThirdPartyUsers. A schema like:
- Id (PK)
- Code (Unique)
It might look like a lot of code and many tables but in this way you can preserve unique user login or you can unify everything under one Master account. I wouldn't merge them automatically but I will offer the user the option to do that. Another thing you need to consider is not to allow users to login or merge accounts before they verified their account. I didn't use a Verified column on ThirdPartyUsers table as I don't want to verify this type of users but you can do this as well.
By using a Codes table you can extend your third party login providers without altering other tables.
I have a database and normally users are the central object.
In database I have a tables roles and users in roles so I can give users different permissions on site.
But now I have one doubt.
I saw before one database with structure like this (User is in 1:1 relation to other tables):
User{UserId, Username, Email etc.}
Admin{UserId, some specific columns}
Child{UserId, some specific columns}
Admin{Parent, some specific columns}
and other tables are connected to user not through User table but through Admin, Child and admin.
Because now I design my database I have Users and user can be Admin, CompanyManager and Professor.
I wonder should I design table like I show above or just relied on roles?
What is advantage of the first approach?
And also in my business model User doesn't have to be CompanyManager or Professor so this is actually 1 to 0 or 1 design.
What is a good way to design database with scenario like this?
The advantage of having specific tables for certain types of users is to store information that is only relevant to that class of user.
In your example,
perhaps all users would have a manager - so the manager ID would go in the users column.
managers would have permissions to view certain information, so this would be handled via a role.
only professors would have a Subject, or the "HasTenure" property. So this information would go in a professors table. Using this approach, you avoid the need to have a "Subject" column in the users table, when it is only applicable to a certain subset of users. As such you avoid a functional dependency in the users table, and a violation of 3rd Normal Form.
I prefer this approach:
In this way, you can easily group Roles into categories and assign them to users.
I have added a series of ASPNET database tables for roles, user and membership management to my existing SQL database using aspnet_regsql.exe.
There is already a user table in the existing database which contains information (ID, Name, Address, Postcode, etc) for a number of users. What I want to achieve to associate the new aspnet_Users table with the existing user table.
Is there any option or options for recommendation please? Thanks
Cheers,
Alex
The UserKey, called UserId in the ASPnet membership tables, is the GUID which identifies a user. You can add a UserKey column to your Users table and then start doing dangerous things like:
select *
from Users as U inner join
aspnet_Users as aU on aU.UserId = U.UserKey inner join
aspnet_Membership as aM on aM.UserId = aU.UserId
where U.UserId = #UserId
No warranty, expressed or implied, is provided by Microsoft (or me) if you want to fiddle about directly in their tables.
We had a similar situation on a project I worked on a couple years ago. What we ended up doing was storing the primary key of the related user record from the external user table as a Profile Property of the ASPNET Membership model.
The benefit was that we didn't have to change anything about the schema of the external database to create the relationship and we could use the built in ASPNET Membership profile objects to easily obtain the related key from within the web code-behinds.
The initial population of this profile property was accomplished via a utility we wrote specifically for the task using ASPNET Membership Profile objects and was made easier by the fact that both our Membership setup and external table stored the email address of the user making it the key for the one time task.
The downside of this approach is that the ASPNET Membership Profile table is very much NOT denormalized (or realy normalized for that matter). It stores the Profile Properties as either xml data or serialized binary. In older versions it was serialized with the property names stored as names and character position of a single value string containing all values. This makes it hard (if not impracticle) to write queries, joins, etc from the aspect of your external table.
For us this wasn't a big deal because we were only working with the external user data on a case by case basis from the website. So, grabbing the key from the ASPNET profile using built objects and then looking it up in the external database was easy.
If your project is going to do a lot of relational queries or batch processes then I would probably recommend instead storing the ASPNET UserId GUID as a foriegn key in your external user table or if emails are going to be unique using those.
I have different 3 types of users and each type of user can have columns and relationships with tables that another type doesn't, but all of them have login(Unique) and password,
how would you do:
create a table for each type or
create one table for all of them or
create a table for all of them only for login and password and separate for all the other things and bind them with a FK
something else
Number 3 is the best of the options you suggested (updated slightly for clarification):
create a table for all of them for login and password and anything else that is shared and a separate table for all the other things that are not shared and bind them with a FK
Except don't store the password, store a hashed version of a salted password.
An alternative might be to assign groups and/or roles to your users. This might be more flexible than a fixed table structure, allowing you to add new roles dynamically. But it depends on your needs whether this is useful for you or not.
As Aaronaught pointed out, in the main table you need an AccountType to ensure that a user can only have one of the roles. You must remember to check the value of this column when joining the tables to ensure that a user has only one role active.
A unique constraint on the foreign key ensures that a user can only have a role once.