Multiple Login Feature - multiple-login

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.

Related

Adding ASP.NET Identity to an existing project with already managed users table

I have an existing web api project with a users table. In general User is involved in some key business queries in the system (as other tables keep its 'UserId' foreign key).
These days I'm interested in adding Asp.net (core) identity. Basically I've already performed the required steps adding a separate Identity table, managing an additional db context (implementing IdentityDbContext), and also added a JWT token service. It looks that everything works fine. However I am now wondering how should I "link" between the authenticated user (which has logged in through the Identity module) and the user which is found on the other original "business related db".
What I was thinking of is that upon login, having the userId retrieved from the original Users table, based on the email which is used as the username and is found on both the original Users table and the new Identity table, and than have it kept as a Claim on the authenticated user. This way, each time the user is calling the API (for an Authorize marked action on the API relevant controller), assuming is authenticated I will have the relevant userId on hand and be able to address and query what ever is needed from the existing business table.
I guess this can work, however I'm not sure regarding this approach and I was wondering if there are any other options?
Regarding the option I've mentioned above, the main drawback I see is that upon the creation of a new user, this should be performed against 2 different tables, on 2 different DBs. In this case, in order to keep this in one unit of work, is it possible to create transaction scope consists of 2 different db contexts?
You're on the right track.
I faced similar problem
Imagine two different microservices.
Identity-Microservice(Stores identity information (Username, Password Etc...))
Employees-Microservice (Stores employee information (Name, Surname Etc...))
So how to establish a relationship between these two services?
Use queues(RabbitMq, Kafka etc...)
An event is created after User Registration(UserCreatedEvent {Id, Name etc..})
The workers microservice listens for this activity and records it in the corresponding table
This is the final state
Identity
Id = 1, UserName = ExampleUserName, Email = Example#Email Etc...
Employee
Id = 1, Name = ExampleName, Surname = ExampleSurname Etc...
Now both services are associated with each other.
Example
If i want to get the information of an employee who is logged in now.
var currentEmployeeId = User.Identity.GetById()
var employee = _db.Employee.GetById(currentEmployeeId)

Best way to mimic inheritance in postgresql?

For an application I am writing, there are two types of "users", those who have made accounts and those who have not, virtual_users. These two types are nearly identical, except account_users have a password, and email is required and must be unique amongst all account_users, although it can be the same as any number for virtual_users. A large number of tables have a column that references users, which should include both, and 90% of app functionality treats them as interchangeable. What is the best way of handling this? Some options I have considered:
-Put both types of users in the same table and have a complicated constraints regarding uniqueness, basically, if password is not NULL, email must be unique among all users where password is not NULL. I have no idea how I would write this constraint. On the few occasions I only want account_users query for only users who have a password. This seems like the best solution if I can figure out how to write the constraint.
-Have Account_users inherit from Virtual_usersand Virtual_users has an additional column password and unique constraints on email. From here there are two potential options:
---Have a Users table which includes two columns account_user_id and virtual_user_id one of which is NULL and one of which corresponds to the appropriate user. When other tables need to reference a user, they reference this table. Have all my queries server side for users query both tables and combine.
---When other tables need to reference they reference either table. I don't think this is possible. Have all my queries server side for users query both tables and combine.
Any advice would be appreciated.
I assume the scenario is you have a system which some parts require the user to be signed into a registered account, and others do not, but you'd still like to track users.
Postgres has table inheritance. You could use that, but I'd be concerned about the caveats.
You could put them all into one table and use some sort of flag, like Single Table Inheritance, but then you run into constraint issues. You would then enforce constraints in the model. This should be fine if you have a strong model.
You could have separate accounts and users. Rather than one being a special case of the other, they key is thinking of them as two conceptually different things. In OO terms, an account has a user.
-- Visitors to the site who haven't signed up.
create table users (
id serial,
-- The unverified email they might have given you.
email text,
-- Any other common information like a tracking token
token text
);
-- Users who have registered.
create table accounts (
id serial,
user_id int references users(id),
-- Their verified email.
email text not null,
-- Hashed, of course.
password text not null
-- any additional information only for accounts
);
I like this because there are no flags involved, users and accounts can have separate constraints, and the accounts table doesn't get bloated with users that showed up once and never came back.
You'd access complete account information with a simple join.
select accounts.*, users.token
from accounts
join users on accounts.user_id = users.id
where accounts.id = ?
If you want to delete an account you can do so without losing the underlying user information.
delete from accounts where accounts.id = ?
Systems which require an account use accounts. Systems which don't use users. Systems which behave differently for users and accounts can check if a user has an account easily.
select accounts.id
from accounts
where accounts.user_id = ?
User tracking is associated with the users table, so you have a consistent record of a user's behavior before and after they register.

Database design relations in User and Profile

I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.

Do I need a login table?

Hey guys I have a simple database question. Say I am emulating a university login system.
If i have a student table and faculty table, can I just store the password directly in the corresponding table? For example student table has such attributes as (student_ID - primary key), First_name, Last_name, Classification, and now I would add a password field.
If I create a login table i'm just effectively copying over thousands of potential records. Is there any benefit to creating a login table with say (primary key STUDENT_ID,FACULTY_ID) and a password field for authentication purposes?
Can I increase security on just one table? What is the better approach?
As one student contains only one password, there maintains one to one relationship so there is no need of splitting the table for one to one relationship.
If there is one to many relation, breaking the table will be good such as for storing multiple phone numbers or multiple address of a user.....
You need to decide upon whether only students will be allowed to login into your system.
What about admin user, teachers, etc?
even if there is a remote possibility that a non student will log into the system it is advisable to create a login table with userid and password stored in MD5 encryption

use of views for validation of an incorrect login-id or an unidentified user

I read this on msdn:
Views let different users to see data in different ways, even when they are using the same
data at the same time. This is especially useful when users who have many different interests and skill levels share the same database.
For example, a view can be created that retrieves only the data for the customers with whom an account manager deals. The view can determine which data to retrieve based on the login ID of the account manager who uses the view.
My question:
For the above example , i would have to have a column named Userid/LoginId on my table on which the view is created so that i can apply a check option in the view for this column. and then if a user with a name not in that column tries to enter data , then he/she is blocked.
Yes, you are right. You should
add a column with the user's login or database user name (say you call it username),
each row should have username populated with the login or database name of the person who is allowed to see that row
you can then build a view where you use the builtin functions SUSER_SNAME() (for logins) or USER_NAME (for database names) in your WHERE clause to filter only the rows the user is allowed to see
See Granting Row-Level Permissions in SQL Server (ADO.NET).
You don't have to add a column to the table: it could be more appropriate to instead add a new table to model the relationship.
There's a deisgn rule of thumb that states a table should model an entity or a relationship but not both. Let's say the table in question models the companies a customer owns (i.e. an entity table) and the business rule states the the account manager can only see companies relating to customers he looks after.
Is account manager an attribute of a company? No, so account_manager should not be a column (attribute) in the Companies table.
Is there a direct relationship between account_manager and a company? No, so a relationship table between is not due here (because the relationship is indirect).
Rather, the direct relationships are between account manager and customer, and between customer and company respectively. There should be two tables whose sole purpose is to model these relationships.