How to link different authentication providers in azure mobile services - authentication

What is the best practice in azure mobile services to use different authentication providers (Facebook, Google, Windows e.t.c.) and understand that this three logins belong to the same user.
Out of the box if a user1 choose to use Facebook for authentication on his mobile phone and add some information to the app, and later he (user1) try to login with Google on his tablet, he will not see his information. Because they are two different users with different tokens. And I want to take some additional information from authentication providers (email) and has my own user table which contains email and other profile info shared for user no matter what provider he uses. How could I achieve it?
P.S. I use .NET as a backend and Windows Phone as a client

There isn't an out-of-the-box solution here. You would probably be best served by using a lookup table which maps a static user ID that you define to different identity provider IDs. Then, everywhere that you take a dependency on the user ID, you would do a lookup to match the current user identity to your static identifier. Your user ID is what gets stored everywhere else in the database.
The important detail here is that a Mobile Services token maps to a single provider identity. If you look at the user ID, it is actually provider:providerID. So we need to obtain two tokens and validate both together in order to associate two IDs.
On the client, you would have to manually prompt the user to link accounts. You would stash the current token in memory during this process, log in with the new provider, then call and API on the backend which does the association.
string existingToken = App.MobileService.CurrentUser.MobileServiceAuthenticationToken;
App.MobileService.Logout(); // allows login with new provider
await App.MobileService.LoginAsync("google");
await App.MobileService.InvokeApiAsync("associateToken", existingToken);
On the server, you need to be able to validate existingToken (the new one being implicitly validated by restricting the API to AuthorizationLevel.User)
Within that API, you can validate the token using:
IServiceTokenHandler handler = this.Request.GetConfiguration().DependencyResolver.GetServiceTokenHandler()
ClaimsPrincipal claimsPrincipal;
bool didValidate = handler.TryValidateLoginToken(existingToken, ConfigurationManager.AppSettings["MS_MasterKey"], claimsPrincipal);
You should probably also look up the user ID in your lookup table to avoid conflicts.
So overall that's a rough sketch of a possible solution. Unfortunately there isn't anything more turnkey.

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.

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

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.

IdentityServer 4 and scope specific user settings

I plan to use IdentityServer 4 on ASP.NET Core with ASP.NET Identity as the data store. This is the first time I use a central authentication/authorization and I am wondering how to solve the following question:
Assume I have users with claims like name, role etc. and a Web API (scope) that allows these users access to measured values from hardware devices. IdentityServer will allow me to authenticate known users but now I need an access control that knows which users may access which device data.
Where do I store this information? Since it is specific to the scope I guess it should not be stored in the IdentityServers store. On the other hand, if I store it in the scopes own database I somehow need to connect it to the users defined in the IdentityServers store. Should I define user IDs that are unique to all scopes and IdentityServer?
You will need to correlate the User Ids that IdentiyServer returns with users defined in the scope's database.
I believe that there is a User table and a UserLogin table where you could track the different logins for each of your users.
Then, in the scope's database, you can then specify which users have access to what device data.
This is a bad idea and will probably lead you down a road that you should not.
This means that your client application requesting the scopes will need to know which user has access to which scopes even before requesting a token from your IDP (otherwise your token request will not work). Rather model these as user claims. Then on your WebApi you can do normal claim based authorization.

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)

WIF STS, different "kinds" of users, applications and claims

We are currently looking into implementing our own STS (Microsoft WIF) for authenticating our users, and in that process we have come up with a few questions that we haven’t been able to answer.
We have different kinds of users, using different kinds of applications. Each kind of user needs some special types of claims only relevant for that kind of users and the application belonging.
Note that we do not control all the clients.
Let’s say that all users are authorized using simple https using username and password (.NET MVC3). A user is uniquely identified by its type, username and password (not username and password alone). So I will need to create an endpoint for each user type, to be able to differentiate between them. When a user authorize, I’ll issue a token containing a claim representing the user type. Is there an easier way for doing this? Can I avoid an endpoint for each user type (currently there are three)?
My token service can then examine the authorized users’ token and transform the claims, issuing a token containing all the users’ type specific claims. So far so good, except for the multiple endpoints I think?
If I need to have multiple endpoints, should I expose different metadata documents as well, one for each endpoint? Having one big metadata document containing a description of all claims, doesn’t make any sense since there is no application that needs all claims.
Update
Some clarifications.
Certain applications are only used by certain types of users. Not one application can be used by multiple user types.
Depending on what type of application the request is coming from, username and passwords needs to be compared for that user type. There are user stores for each type of application. That is why I need to know what application type the request is coming from. I can't resolve the type by the username and password alone.
Based on your problem description, it sounds like you have three indepent user "repositories" (one for each user type).
So imho this would be a valid scenario for three STS or a STS with multiple endpoints.
Another way to solve this could be to distinguish the user type by the indentifier of the replying party redirecting the user to the sts. This identifier is submitted in the wtrealm parameter.
The processing sequence could look like the following:
Get configuration for relying party (wtrealm) from configuration store (I'd suggest a database for your rather complex case)
Validate user with username, password and user type (from relying party configuration)
Add claims depending on user type or relying party specific configuration.
The datasbase/class structure for this could look similiar to this:
Need some more information to answer:
Are certain applications only used by certain types of users? Or can any user type access any application? If the former, you can configure the STS for that application to pass that user type as a claim. Each application can be configured to have its own subset of claims.
Where is the user type derived from? If from a repository, could you not simply construct a claim for it?
Update:
#Peter's solution should work.
Wrt. the 3 STS vs. 3 endpoints,
Many STS - can use same standard endpoint with different "code-behind". Would still work if you migrated to an out-the box solution . Extra work for certificate renewals.
One STS - custom endpoints won't be able to be migrated. Only one STS to update for certificate renewals.
Metadata - given that it can be generated dynamically, doesn't really matter. Refer Generating Federation Metadata Dynamically.