Database structure for multiple authentication sources of users in a web app - authentication

I'm trying to work out how to structure a database schema that allows me to have multiple authentication sources for the same end-user.
For example, my web app would require users to sign in to utilize many of the functionality of features of the app. However, I do not want to be responsible for storing and authenticating user passwords.
I would like to outsource this responsibility to Google, Facebook, Twitter and similar identity providers.
So I would still need a database table of users, but no column for a password. However, these are authenticated would not be my concern. But I would still need to somehow associate my user with the identity providers user id. For example, if my user signs up with Google, I would store the users Google ID and associate this with my user. Meaning next time the user makes an attempt to login and is successfully authenticated at Google, I would make an attempt to find any user in my system that has this associated user id.
I've been trying to look for some common and recommended database structures, with no luck. Maybe I'm searching for the wrong terms for this because I cannot imagine that this is an uncommon way to do it. StackOverflow seems to do something similar.
The way I imagine it, it would allow me to associated multiple authentication sources for one app user. Meaning once I've signed up with Google, I can go to my settings and associate another account, for example, a Facebook account.
How should I go about achieving this in a flexible and clean way?
Thanks.

You need to know what data you have to save in your db to authenticate a user with a third party login.
For example, once I used Google to login users in my app, I save Google user id first time a user logs in and get data the next time.
You could have an entity with third party providers, so you will create a table with 2 values, user_id (your user data) and provider_id (Google, facebook, twitter...).
If you are going to use just one provider then you could add provider_id field to your users table.

Related

How to manage user updates and deletions in OIDC and SPA architecture

i am making a set of applications that share a common oidc provider (in my control), where the users will be created.
One of my applications is a stateless SPA "meeting" app where you can schedule meetings with other users, and you login purely by an OIDC token.
I am having a hard time thinking a strategy about the following
Should the "user" details be stored in the meeting app after a login? So let's say user A exists in the provider, then enters the meeting app. Should i save user A in the meeting app DB?
How to handle change of user details? Let's say user A changes name to User B in the provider. Until he logs in again, all the other users see him as User A still in the "contacts" list. What is the usual practice for solving this?
How to handle deletions in the provider. I need someway to signal that "deleted in provider -> deleted in app". Should i constantly poll the provider and get any missing users, create a push system, or is this just unneeded?
Thanks a lot in advance
That's actually a very good question and rarely explained well in online articles. Hopefully the below detailed notes help you with your solution. I have answered your questions at the end.
OAUTH USER DATA
Typically the core user data such as name, email etc belongs in the Authorization Server. It contains Personally Identifiable Information (PII) and changes are audited there. This is explored in further detail in the Privacy and GDPR article.
DOMAIN SPECIFIC USER DATA
This might include fields like a user's application preferences, and you may end up with data similar to this in your APIs:
Field
Description
id
A database surrogate key for the user
subject
The subject claim from an OAuth access token, which is typically a GUID or something similar
archived
A boolean flag set to true when a user is active in the app
field 1
A domain specific value
field 2
A domain specific value
To get OAuth user data within your applications your APIs can call the Authorization Server's SCIM 2.0 endpoint as described in this User Management article.
AUTHORIZATION AND ROLES
Interestingly, roles and application specific rights could be stored in either of the above data sources. You may want to start by putting roles in the OAuth data, but for cases where they are very domain specific and change often, I have found that storing them in my own API data works best.
DOMAIN SPECIFIC USER DATA AND ACCESS TOKENS
Sometimes you need to include domain specific user data (which might include roles) in access tokens. This Claims Article explains how claims can be looked up from external APIs during token issuance. This typically involves a REST call from the Authorization Server to one or more APIs, providing the subject value for which tokens will be issued.
CONSISTENT USER IDENTITY IN YOUR APPS
A user can potentially authenticate in multiple ways, such as default password / corporate login / social login. You may need to use some custom Account Linking logic to ensure that the subject field in the access token gets the same value in all cases. This prevents you ever creating duplicate users within your application.
USER INFO CHANGES
These are typically made by end users within an application screen, and your APIs then call SCIM endpoints to update the core OAuth data. A common case is when a user changes their name and / or email, eg if the user gets married. Note that the subject value remains the same after this edit.
USER ADMINISTRATION
In scenarios where corporate assets are used, an administrator typically provisions users, either individually or in bulk. This can be done via the SCIM endpoint. In some cases administrator actions may need to save data to both data sources - eg to create a user and set roles + application preferences.
USER INFO EVENTS
Sometimes your application needs to know about a user info event, such as new, deleted or changed users. This can be managed via Event Listeners, where an extension to the Authorization Server calls back your domain specific APIs when a user edit occurs. When a user is deleted in the OAuth user data you might then update the user's application state to archived.
DATA MIGRATIONS
Finally it is worth mentioning that the above also supports migrating to an OAuth architecture or between providers:
Get a combined view of the user data before migration
Insert all existing users into the new OAuth system via SCIM
Update the combined view of the user data with new subject values
Update your domain specific data with new subject values
SUMMARY
So to answer your questions:
Aim to avoid this because it adds complexity, though in some cases you may need to denormalise for performance reasons. The OAuth user data should remain the source of truth and the only place where edits occur to PII data.
Your meeting app would need to join on the OAuth user data and domain specific user data and present a list. This would probably involve caching a combined view of the user data.
See Administrator Events above. Your API should be informed of OAuth user data changes via an event, then your SPA would get current data on the next refresh.
When implemented like this you end up with simple code and a well defined architecture. Some providers may not provide all of these features though, in which case you may need an alternative approach to some areas.

How to associate data with a user that has been authenticated with Google oauth?

So I am having some trouble figuring out how to implement a sign-in for my app using google oauth. Every example I see shows how to authentication the user, get their permissions and then start using the Google APIs.
I do not care about permission or using Google APIs. All I want to do is have the user sign-in to my app using google oauth instead of having to implement my own authentication system with user and passwords in the database.
After the user authenticates with their google account, then they can change settings associated with their account for my app. What is the flow i need to implement to achieve this?
How would I associated a google user with certain data defined in my own app's database? I have successfully implemented the authentication part but then what would I need to store in my DB to associate them with their actions and data. Would I need to use sessions? and then retrieve their Google+ ID, save it in the database and then use that to identify them in the database for later when they log in again?
any help is appreciated
Once the the server validates the access token, a user account can be created in the database, saving the Google ID along other user details (ID, email, name etc).
If your application also supports normal registration, and an account is already present for that user (matching email), then you can just fill in the (nullable) Google ID column in order to link the account(s).

How to implement a one time authentication mechanism?

I'm trying to create a website to authenticate users through the use of a throwaway password where the assumption is that the user might not use the website again (basically a one time access).
I have done my research on OTP and various solutions to authentication but these don't seem to fit my requirements, most of them seem to rely on users having login credentials to the website whereas my system would allow them access without the need for registering.
The implementation of passwordless authentication by Auth0 seems to fit what you're describing. Even if you were not considering a third-party provider it may be useful to go through the documentation.
Basically, a user can login to a site without any need for a sign-up process. They can do so just by requesting that a one time code is delivered to them, for example, either by email or SMS.
This way, they can get quick access without having to setup a user and in the event that they do come back your application can recognize this because they will most likely be using the same mechanism, that is, you can use the email or mobile phone as the unique identifier.
Disclosure: I'm an Auth0 engineer.
If you do not require your users to register, why do you need authentication at all?
Why not just set a cookie with an unique identifier on the first visit? You can store data at the server side associated with that identifier. Keep track of when you last saw the user, and if they do not return within a certain period, you can delete any data you stored for that user.

JSON Web Token (JWT) - one account multiple users

If I'm using JWT to authenticate users to get access to my API, would it be possible to create one "generic" account for many users to use? That way, users who don't have a "real" account, would be given this generic account credentials in order to access the API. Would that be possible? Because, I'm wondering, with JWT, if one users log in, would I invalidate the other user token?
If that approach would not work, what would you recommend?
The reason: I want my app to communicate with my server, even if the user doesn't have an account created. But I would not like to keep that "door" open, hence I would like to add some kind of authentication for those people who are using the app but don't have an account. Suggestions?
Create accounts connected with accountgroups. This way you are also able to create temporary accounts having less permissions for example. And multiple clients are able to access same data and same time.
So the Payload is owned by the accountgroup, the client authenticates with a (maybe temporary) account and gets authorization via accountgroup.

Associate multiple claims based identity providers to one user with ASP.NET

In an ASP.NET MVC 4 application using the .NET 4.5 framework in conjunction with Azure Access Control Service (ACS), I want to provide the users multiple authentication possibilities (i.e. Google, Facebook, Windows Live, etc.). What is the "best practice" for associating a single user to multiple identity providers?
For example, say the user logs in with Google one day, then goes to another browser the next day and logs in with Facebook. How would I know to associate the Facebook login with the previous Google login to the same user?
Look no further than stackoverflow itself for a good example of this. Click your user profile and then select "my logins".
When a user creates their account, they select which identity provider you want to use to sign in. Under the hood, your application creates a new site-specific unique user ID, and links it with a 3rd party provided unique ID. (You might use email, but most identity providers will also provide a unique user ID claim that doesn't change, even if the user changes their email)
Now, after the user has signed in, they have an account management control panel through which they can establish additional links to other identity providers.
I see two options for achieving this:
Have your MVC application persist account links. When a user signs in, you query your account link store using the 3rd party unique ID claim and resolve your site specific unique user ID.
Use the ACS rules engine. You would create one rule per account link. For example, lets say I can sign in with either gmail or liveid and my unique id is 1234. Two rules look like this:
google + me#gmail.com --> output user ID claim 1234
liveId + me#live.com --> output user ID claim 1234
For the unique ID output claim type, you can pick from the available claim types or designate your own. ACS has an OData based management service which you can use to create these rules programmatically from your MVC application. Here's a code sample.
If you are using ACS, you can translate the information from each IdP (e.g. Gogle, Yahoo!, FB, etc) to a common handle using claims transformation on ACS. A common handle people use is the users e-mail. But if you want to accept many e-mails mapping to the same user, then you'd introduce your own unique id (as a claim) and map IdP supplied claims into it:
myemail#gmail.com (e-mail - Google) -> (UserId - YourApp) user_1234
myotheremail#yahoo.com (email - Yahoo!) -> (UserId - YourApp) user_1234
64746374613847349 (NameIdentifier - LiveId) -> (UserId - YourApp) user_1234
You can automate this through ACS API. You should also probably handle the first time user logs in into your site (e.g. asking user for an e-mail and sending a confirmation message that will trigger the mapping).
Presumably, you are using this information to retrieve data from a local database in your app, otherwise, you could just encode everything in claims and not worry about any equivalences. Claims are often a good place to encode common profile data. (e.g. Roles, etc)