IdentityServer, clients and user profile management - asp.net

In instances where you have multiple clients and a central IdentityServer 4 instance which handles user auth/n, how would you go about managing user profiles from individual clients?
Current scenario:
user clicks on manage profile
user is redirected to a custom manage claims page on IdentityServer which a) loads all claims in a form, b) allows user to mod such claims and c) updates them with new values
user is redirected to the referrer URL (which then retrieves
these fresh claims via a token refresh which includes the profile
scope) - although a redirect is not always possible, or is frowned
upon from a design perspective (users' experience is broken since
they are taken to a different location with a different design).
Desired scenario:
user clicks on manage profile
user is redirected to a profile page on the client itself (e.g. SPA or desktop), populated with info from the profile scope
user updates profile data, and client then makes an API call to IdentityServer to update the users' claims centrally
local claims are refreshed to reflect claims sent to Identity Server
Main concern: is this a sound approach architecturally speaking? Should user profiles (e.g. first/last name, gender, DoB, etc...) be managed by IdentityServer (via an API or own pages) or should these be stored centrally and used/managed by both IdentityServer (loaded as claims) and individual client apps? How would you go about tackling the desired scenario?
The closest info I got was in method 3 discussed here.
... however it's a 3+ year old doc, and am not sure what is recommended by oidc-client/IdentityServer 4 devs today.
Any insights would be highly appreciated.
Chris

I believe the main reason for the need of the second scenario could possibly be
taken to a different location with different design
Is it?
If it's not, I don't see any benefit from repeating the same or similar claim update page on multiple client apps, if there are more than one.
If it is and you can't customize the page on your identity provider (the Identity Server), you can still have a single claim update page but just hosted outside of the Identity Server. This page (formally: the app that hosts it) would be the client of the identity provider as well as the client app that redirects here.
A benefit of this approach is that you could have a total control of how this page looks like, event make it conditional depending on the client.
Should user profiles (e.g. first/last name, gender, DoB, etc...) be managed by IdentityServer (via an API or own pages) or should these be stored centrally and used/managed by both IdentityServe
There is no single answer to this as it totally depends on you actual business background.
It's even worse than you describe, you can have a hybrid system where some claims are shared by multiple subsystems but other subsystems have their own profiles not shared with any other subsystems and all these are integrated around one identity provider.

Related

OAuth2 protected API. How to allow customer's to SSO using its own authorization server?

I have an Angular Single Page Application (SPA) talking to my ASP.NET API.
The API is protected by my own Oauth2 server (IdentityServer4).
One of my customers (let's call him X) wants SSO: Their users on my platform would sign in on their server instead of using the login form in my app that connects to my IdentityServer.
Each customer has its own subdomain for the Angular SPA (e.g. x.myapp.com). Therefore I can easily redirect X's users to their server's authorization page to approve my API, based on the hostname.
However the API itself uses one common hostname for all customers(api.myapp.com). Customers are distinguished by the Origin header of the API call (x.myapp.com) during the login call (and a few other unprotected calls) and by the Bearer token for protected calls to the API.
How does my API introspect the Bearer access token? Who should know which server to query ?
Is it the responsibility of the API server? Or can I tell my IdentityServer about X's oauth2 server ?
X's users would also be defined on my platform since we need specific info (such as config of roles on the platform). My current setup implies specific claims (such as user id) that allow my API to know what the user can do. Obviously, X's server will not provide the same claims. How can I connect the dots ? e.g. get some standard claim from X's server (username, email, whatever) and match it to my list of users.
Note: This question is similar but the answer is not accepted and seems to imply that the provider of both identity servers is the same (not the case here).
Formatting my comments as an answer:
From reading your question it's pretty much clear to me that you could benefit from what is know as Federated identity.
As you said, one of your customer want to achieve SSO - They want users to login using their existing accounts and be able to user your systems normally.
Since you already have an IdentityServer in your domain, what you can do is delegate the login part to the customer's side (whatever they do it). This is illustrated in the Identity server documentation Federation Gateway.
Basically, the approach is that upon hitting the "login" button in your front-end, you would redirect the users to your Identity Server passing some special params (prompt and acr_values for ex) which in turn, tells identity server to redirect the user's to the external Identity provider (the customer's). After a successful login, you have a chance in Identity Server to augment the claims, maybe using something they returned or anything really. Then the process is as normal - you return a JWT Token generated by your Identity Server
The benefit of doing this is:
Your SPA/API doesn't have to change. You will still work with your own bearer tokens and can continue doing authN/AuthZ as before.
You have a chance to add claims that might indicate where this user is coming from if needed
If your customer's server changes, you don't have to worry much, apart from maybe some tweaks related to returned claims
They don't necessarily need to use OpenId/OAuth on their side for this to work
Useful things you probably will need is some params to pass during the call to the authorize endpoint in Identity Server. (acr_values and prompt).
You can also check this in the quickstarts, by looking at Sign-in with external providers (which is pretty similar to what you want)
Now to your individual points:
Your Identity Server should be the "bridge" between you and the customer's "identity provider".
Upon a login from an external provider (X), you need to somehow identify the user on your platform. You could use email or, even better, if X is already using OpenId/OAuth they might give you the sub claim which is the user id on their side. At this point you need some sort of agreement with them otherwise this might be flaky/unreliable for both sides.
In a more "advanced note" you could also add to your tokens some sort of claim that tells you who is the source provider of this user. Here the source provider would be X. This is useful because you might want, for example, configure allowed identity providers in your app, or maybe enable features only for certain providers. Like, ppl logging in with Google might only see certain parts of the app.

Retrieving all users and roles in a .NET Web Application through ADFS

We have a hosted .NET web application (Windows Server 2012 R2 environment) and we need to provide Single sign-on (SSO) to users from a corporate LAN environment. We have used ADFS to enable SSO and it is working as expected thus when a user hits our web application login page URL he is authenticated against ADFS and is automatically logged in to the application.
We have an additional requirement where we need to obtain a list of all users, their groups, email addresses some additional information periodically from their Active Directory so that this information can be bulk loaded into our web application however since ADFS is implemented we do not have direct access to the Active Directory.
Is it possible to connect to ADFS and obtain a list of all users, their email addresses etc. programmatically?
If the above is not possible then what is the recommended approach for this kind of a setup?
Thank you.
No, this is not possible. There is no such API because with SAML and WS-Federation, users can come from anywhere. This does not have to be AD, technically it's possible create a "Log in with Facebook" implementation.
What would you need the information for? The user's claims contain all information which you might need (user name, e-mail address, group memberships).
If you really need that information about all users in your application, perhaps ADFS is not the solution you are looking for.
As Alex mentioned above - the way it works, ADFS does not provide any way of importing data from the AD or other trust stores. It just gives you the information that are carried over with the token.
In case you need more information, you should extend the number of claims being issued by ADFS. You can then collect the information - when the user comes for the first time, use the data from the token and fill the profile. If it is returning user - update the information if necessary.
The other solution (but I wouldn't say it's recommended - rather a workaround) would be to implement custom solution for importing information from AD to your application. I'd say it's fair as long as you use your local AD for reading this data. In the moment you decide to extend the access to third party (e.g. partner company), which might be using different identity provider, which doesn't have to be backed by Active Directory any more - you find yourself in tough spot.

Multiple site domains and virtual directory single login

I am creating a project which has a login portal with multiple applications and websites. I want to allow the user to login and then click any application and have access to it. Some considerations are: each application is defined in a user profile, ie which users can see what. also each application privileges are different for each user. so user a may be an administrator of application a but just a normal users in application b.
What i know.
I can have one auth cookie created in the main portal which with setting the machine key and same authcookie name, each application can use it. I have done a test with this and it seems to work.
My problem
As each site/ virtual directory has different privileges per user and per application when the user access a site i need to get his privileges from the databases but I cant then overwrite the auth cookie userdata with the new details because he may have multiple tabs etc open at a time on different sites. So how can i have an extra cookie store per user and per application for holding application specific details. I know I could go to the database each time but that's allot of overhead for each post back.
Maybe another option is to use the main authcooke for checking the user is logged in then have a new auth cookie per aplication and user, but how can i have 2 authcookies, that may get confusing and the second needs to timeout when the main one does et c i think
Any help suggestions would be gratefully appreciated
THanks
------------------- EDIT -----------------------------
we have one user table for all all sites not 1 per each site. then we map the user to an application and then the user application and role. so when you get to an application it has to check if the user has access and what there role is. all other user details are already in the auth cookie when loggedinto the main site. We do it this way because we have to manage users in one application not each application. Hope this helps understand my requirements.
What you are describing is a 'classic' SSO (single sign-on) example. There are lots of ways people have tried this and they are well documented on Google.
One way to do this is to have your SSO server (e.g. the first place you land and log in) to issue a security 'token' (e.g. a Guid) and then either store this in a cookie or append to URLs. Each subsequent call to an application can look-up the token in a database, verify it's validity and carry on (or boot the user out if invalid).
Using a database also allows you to set a timeout for all applications for which the token is valid.
This can then be extended to allow the database to store which apps each user can access etc. I've described this in very broad terms but it may be a good starting point.
Hope this helps
BTW: querying the database on each request isn't too much of an overhead. I have applications that do just that and are still performant when loaded with 300+ users.

Fetching logged user information in Alfresco

We have a requirement to enable drag and drop of content from Alfresco to a PLM application. Now we have created a new custom view with the PLM product and have incorporated an SWT browser in that view. The idea is that the user would enter the alfresco url and he would be able to drag and drop contents from Alfresco to PLM product using this new view.
The trouble here is that we are being asked to develop it as a single sign on application. The moment the URL is entered by the user, alfresco would ask the user his login credentials.
The user authenticates himself and would be able to view different documents.
But in order to actually download them, we need to set the user info. specifically the user name and password in the request to Alfresco. This is where we got stuck.
Is it possible to get a session or an equivalent identifier codefully [ Note that user visited alfresco url and has authenticated himself. So, we dont have any hold of his information there. ].
Requesting you to share any ideas...
Thanks,
Pavan.
Note: A new UI that would prompt the user to enter user name and password might be possible. But we do not want to resort to that approach.
First, some background.
Most web SSO systems work by authenticating the user themselves, and then setting a custom HTTP header containing the user identify (normally a plain username) which is sent to your web applications by a proxy. I'm not sure if that would work for you, but you may wish to investigate integrating CAS with Alfresco, assuming that both your applications are webapps.
Other options for SSO with Alfresco which might work for non-webapps are NTLM (old and insecure) and Kerberos (much more secure; recommended). These normally integrate with your operating system login session but must be configured in the user's web browser as well as in all the applications that you wish to SSO enable.
In summary, there are a few options that may be available but it depends on the nature of the second application that you want to integrate Alfresco with. I would suggest that you do some further technical investigation based on these areas and any others which others might suggest, and then come back with any specific questions that you have.

SSO - Share single User table between several websites or somehow keep multiple User tables in sync?

I'm working on a single sign-on solution for two ASP.NET MVC3 websites. The sites are on separate subdomains. I'm using Forms Authentication and so far I everything is working well. When I sign into a.example.com I'm automatically signed in to b.example.com too. Nice.
Each application has its own database.
My question is this - if I want to keep certain user information in sync between the two sites (say the last activity date or some user preference) then should I have a User table in both databases and somehow keep them in sync or should only a.example.com's database have a User table and b.example.com somehow reads and writes to it?
Thanks for your advice.
Edit: Thanks to adam I'm leaning towards storing all user data in a separate database. I will pass the authenticated user's username and ID to each application in the authentication cookie. Can anybody offer any advice around maintaining referential integrity between the two databases?
Most SSO solutions I've seen have a central accounts portal where users can maintain settings, change email address etc.
Think Google:
google.com/reader
google.com/analytics
google.com/accounts
This represents a single user store, providing authentication to several sites. This has various benefits, such as a single place to store session hashes and other security details (for preventing things like man-in-the-middle attacks).
In a true SSO, an authentication request redirects to the central auth system (ie google.com/accounts), authenticates and then redirects to the service that requested authentication.
From your description, it sounds like you have separate authentication for each site/service, but the user db is shared.

Resources