Standalone identity server 4 Username lookup - c#

What is the recommended way to obtain user details from standalone identity server 4?
I have an api and auth server as separate entities. Lot of resources in api have auth user ids attached to it and on UI I would like to display real user names. While there is an obvious solution, add api methods to identity server that would return these based on provided ids, I was wondering if there is any best practice concerning this.
I have some weird feeling about exposing user info in api even if it's lookup based on id. Theoretically anybody can obtain these ids. I am only interested in given_name, family_name and username claims so maybe these are public enough and I am overthinking.
Other option would be to setup server to server communication which increases the load though so I am not very excited about that tbh. How are you dealing with this?

We have an Authentication Server(IdSrvr4), and an Authorization Server.
If you have said user's token, use the built-in Identity Server UserInfo Endpoint.
For anything custom, we implement in Authorization Server. So If you want given_name and family_name of other users, we have a custom endpoint for that. And that custom endpoint uses custom Authorization Filters and uses a direct call to the database(We use EF & MS Identity).
Update due to Comments.
We chose 2 Servers, 1 for Authentication and 1 for Authorization. This design was in part informed by this article titled "Identity vs Permissions" and written by an author of IdentityServer4.

Related

Identity server 4 and user permissions

we are using identity server to grant access to apis. All what we used (or needed) so far was ClientCredentials (machine to machine) where the user is not involved.
Now we got the requirement that users should be involved and we must deliver user permissions.
I have read a lot about Granttypes: Implicit, Authorization code, Hybrid etc... but still didn't find a clear answer about the best practises.
Is there any way to integrate user permissions in access_token (is this also a good idea?). The AspNetIdentity is already integrated and the tables are existing in identityserver database.
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<IdentityContext>()
.AddDefaultTokenProviders();
How to send client credentials and user credentials so our identity server can also collect user information (permission, claims, role, etc...)?
Any help is highly appreciated.
Thanks
You're confusing concepts here. Identity Server deals only in user principals (basically just a set of claims belonging to a "user"). The actual user management is out-sourced, most normally to Identity. Identity itself is claims-based, as well, with roles actually just being a type of claim.
Authorization is a whole other beast and doesn't technically explicitly involve either Identity or Identity Server, although they often act as the gateway to said authorization. Authorization can be role-based, claim-based, or policy-based in ASP.NET Core, and then there's the technically framework-agnostic resource-level authorization option. However, that's still going to ultimately rely on one of the big three: roles, claims, or policies. It will simply have an added component of being specific to a particular resource. Which way you want to authorize is entirely up to you and of course you can mix and match as well.
Ultimately, you're just going to set roles and/or claims on your user via the tools Identity provides, which of course, will be persisted to you user/role store. Then, when authentication occurs via Identity Server or directly, a ClaimsPrincipal will be created and added to HttpContext. When authorization is required, the claims on this principal will be utilized in some way to determine whether access should be allowed or not. Simple as that.
Identity Server simply acts as a centralized authentication provider. Since communication is happening over HTTP, it's actually going to be returning JSON, specifically a JWT. Then, ASP.NET Core's authentication middleware, which would have been set up to use Identity Server as its provider, would simply decipher the JWT and create the actual ClaimsPrincipal instance from that. You don't need to worry about any of that, though, past the initial implementation. Once everything is integrated, the fact that Identity Server was used is virtually inconsequential.

MVC authentication with additional user details

We are currently starting to use MVC and are now looking at authentication. .net Authentication isn't necessarily our strongest point, so looking for some advise or pointers.
Our current set up:-
Basic Windows authentication
system uses the authenticated user to query a 3rd party system to get their current roles
these roles are then stored in session variables and used when ever authorisation is required
Any additional user details are called upon as and when needed from various tables
What we'd like to achieve :-
Basic Windows authentication (perhaps create a forms authentication cookie on the back of it)
System users the authenticated user to query 3rd party system to get their current role/s,
These roles are stored within the cookie, and can be accessed via User.Roles etc
Any additional user details (i.e. user favourite colour) will be called on authentication and store against the user profile. The additional user details will be stored in a single table as key value pairs.
Is this the correct way to go about this? we're struggling to find any samples etc to match the scenario we are after.
unfortunately, we need to use this 3rd party system to access the roles, this is achieved via a web service call.
Are there any new advances with MVC 4 which could greater handle authentication with additional user details?
any help, or advise would be greatly appreciated. :)
Sounds like a perfect candidate for federated authentication. You could even use WIF (Windows Identity Foundation) which is now part of the Base Class Library.
In general, federated authentication consist of following parts: delegating the authentication to an external identity provider, consuming identity provider's response, persisting the identity locally (in a cookie perhaps).
WIF has solutions for all these concerns, it is built around the WS-Federation protocol. The really, really great benefit of this is that you can switch between different identity providers easily. This is something that you could consider useless, until you see it in action and immediately you start to create complicated business scenarios in your head.
Using WIF requires some knowledge and specific questions can be answered easily. However, until you get at least some basic knowledge, this sounds like a mumbo-jumbo. You should definitely start by reading a free ebook, Claims-Based Identity and Access Control from here
http://msdn.microsoft.com/en-us/library/ff423674.aspx
Just download it and start reading. I promise you'll immediately find answers to many of your questions and page by page you'll feel this constant "wow, so that's how it should be done!".
Just to provide a specific answer to one of your questions: user data can be persisted in the authentication cookie. If you stick with WIF's model of Claims, expressing arbitrary data is natural: a claim is a pair (claim type, claim value). This requires however to switch to SessionAuthenticationModule as forms authentication module could possibly produce cookies that are too large:
http://www.wiktorzychla.com/2012/09/forms-authentication-revisited.html
(the session authentication module has a special "session" mode where the large part of the identity is stored locally at the server in the session container so that the cookie is really small)
And yes, the federated identity model works with MVC authorization tags. Claims of type role are interpreted as user roles. The remote identity provider can then even set user roles and you can guard your MVC controllers in the usual way.
If you are lucky your 3rd party component might bring a Claims provider with it so you could use Claims based authentication and let the Claims provider supply the additional user data in form of Claims that you can use in your application. For a tutorial see this link. If you cannot access a Claims provider, the known security building blocks still work for MVC. So for your additional roles, you could create a RoleProvider that requests the roles and configure it in your application. You can then secure your controllers or actions with the Authorize-attribute.
In order to optimize the request for roles so that you do not have to request it from the 3rd party system over and over again, there are some alternatives:
As you propose in your question, you can store them in the cookie. But be aware that cookies are stored on the client computer and could be tampered with. So if you have a Forms authentication cookie that you can use, you could store it in the UserData of this cookie. This cookie is already encrypted so that users cannot change it easily. As you want to use Windows authentication at least in the first step, you do not have a Forms authentication cookie that you could use. In the context of security, it is always advisable to set up upon a widely used and well tested framework, so I'd not recommend to create a cookie of your own and store the roles there (though it wouldn't be a too daunting task in this specific case to encrypt/sign the cookie data).
You could also store the roles in a Session variable. Downside is that the session times out after a while and you'd have to be prepared for this case. On the other hand, session memory is located on the server so that it is not that easy for users to tamper with (and if they could, you'd have lots of other problems).
Another component you could use is the Cache on the server; though you'd have to be careful not to mix data for various users as it is shared among users, it is also located on the server and provides a more fine grained control on when the data are invalidated. So you could configure a time frame after that any user would be authorized with a new role set in case it was changed.
Your RoleProvider would need to implement the caching technology (Cookie, Session or Cache).
As for your last point regarding the user profiles, I can imagine that the User Profiles of ASP.NET 2.0 still work. I don't have any experience with it, so I can't give you a recommendation on whether to use it or not. On the other hand, these data don't seem to be too security critical so you can also store them in a cookie or session memory once the user has been authenticated.

Options for single sign-on between ASP.NET and MVC.NET solutions?

I have an ASP.NET solution that acts as the primary customer portal for my customers. On this website the users can log-in access their important financial information and more. The website uses a custom authentication scheme that checks the user's username (their email) and their password (salt-hashed) against a Users table in a local database.
I am building a new MVC.NET solution that is more of a web-app tool to be used by these same customers for ordering. I want to re-use the sign-on mechanism of the ASP.NET portal to authenticate users. The goal is to save the user from remembering two log-ins or even having to supply the same log-in twice.
What are my options for allowing users who sign on to the ASP.NET solution to then be auto authenticated to the MVC.NET solution? I've listed some ideas below but are these "bad" or is there a more elegant solution? I'd love your input.
Common Cookie I could create a common cookie that the ASP.NET site creates and the MVC.NET site looks for. But is that secure enough?
Token in Query String I could create a token id on the ASP.NET site that is stored in the local database and is then passed in the query string of the link to the MVC.NET site which takes the token id and validates it against the same database.
Hybrid A bit of both?
Other? Got a better idea?
I've recently done something quite similar (the major difference being that it was internal to the company rather than for external customers) using OpenId.
The implementation of OpenId for .NET is called DotNetOpenAuth which should be suitable for your purposes.
It did take me a while to implement; but it works very well, is very flexible, and extremely secure.
More information about openid (from Wikipedia):
OpenID is an open standard that allows users to be authenticated by certain co-operating sites (known as Relying Parties or RP) using a third party service, eliminating the need for webmasters to provide their own ad hoc systems and allowing users to consolidate their digital identities.
Users may create accounts with their preferred OpenID identity providers, and then use those accounts as the basis for signing on to any website which accepts OpenID authentication. The OpenID standard provides a framework for the communication that must take place between the identity provider and the OpenID acceptor (the "relying party").2 An extension to the standard (the OpenID Attribute Exchange) facilitates the transfer of user attributes, such as name and gender, from the OpenID identity provider to the relying party (each relying party may request a different set of attributes, depending on its requirements).
The OpenID protocol does not rely on a central authority to authenticate a user's identity. Moreover, neither services nor the OpenID standard may mandate a specific means by which to authenticate users, allowing for approaches ranging from the common (such as passwords) to the novel (such as smart cards or biometrics).
Oh, and if you'd like further encouragement, Stack Exchange uses it!
#Jmrnet: in response to your last comment:
Perhaps I was unclear. OpenId in and of itself is simply for validating credentials from one location to another (more or less). It's entirely possible to implement as an SSO model where users do nothing different whatsoever - they don't have to choose a provider, or register, or anything like that. For example, in my setup, the user enters a username and password in a web portal, and then clicks a button to launch another site being automatically logged in by OpenId. Nothing different for the user at all! OpenId can be used with any initial authentication model you can think of (note the bolded section in the snippet from wikipedia).
Take a look at SAML:
http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language
It works using XML and supports encryption.
I am currently implementing two SSO solutions for the same project.
In one, we are interfacing with an external partner and are using SAML.
In the other, we are allowing logged in users access to our Sharepoint and using the "Token in Query String" approach, since we trust Sharepoint to access our membership tables. This approach is much easier than dealing with SAML tokens.
There are many methods you can use, Mansfied described OpenID and RandomUs1r described SAML. Also, you can store relevant information in localStorage or in the session. I believe you should store relevant information with session.
It is not safe to put this in the query string, because if I register and log in, I will see something like UserID=1234 in the URL. If I change that to UserID=1235 and the ID is existent, then I can do some things in the name of the other user. This is called identity theft, which should be prevented by any means possible. So you should never have this kind of info in your URLs. Also, if you store the id of the user, you should obfuscate it somehow. For instance if you store the value in local storage and instead of 1234 you store encrypt(1234, salt), then the consistency of user action will be maintained.

WCF, active directory authentication|authorization and user profiles in sql combination

I'm developing a WCF service that will host business logic of the application. The application is mostly for intranet, but can be accessed from internet. We have an active directory domain up and running, so I plan to authenticate and authorize users according to their username and groups they are in. This service will be used mostly be an ASP.NET MVC site
So, first question is how to authenticate and authorize users based on their AD profile?
Secondly, I need to store additional info about each user. The problem is that I can't modify AD scheme. The number of added fields is about 10 or so.
Can I somehow use SQL server for profile storage? Of course I can, but how to tie this with AD auth?
You can use WIF for this.
You would configure your WCF service for WIF in the normal way and then use a custom ClaimsAuthenticationManager class deriving from the base ClaimsAuthenticationManager and overriding its Authenticate method. This is a normal extensibility point of WIF. WIF will
get hold of the security token from the incoming request and add claims for each of the relevant AD properties. In your override of the Authenticate method, you will add new claims to represent your extra properties.
The basic use of WIF for WCF services is described here:
http://msdn.microsoft.com/en-us/library/ee748476.aspx
To see how to use ClaimsAuthenticationManager, start here:
http://msdn.microsoft.com/en-us/library/ee748211.aspx
Well, I think you have a couple of choices here, but you will have to carefully consider the implementation.
The primary issue with using active directory authentication is that by default a user's credentials can only be passed successfully between two machines. In the case of a web application, this means that the user's credentials can travel between the end user's machine and the web server, but no further.
However, this behavior can be changed through the use of Kerberos authentication, which essentially allows an authentication ticket to be passed among all of the trusted machines in the chain (i.e. from the web server to the application server to the database, for example). Successfully configuring Kerberos can be extremely challenging, especially if you have had no prior experience with it.
I think your best bet is to configure your web site to accept only Windows Authentication. This means that IIS will perform the validation of the user against active directory. In your ASP.Net application you can pickup the domain name of the authorized user from Request.ServerVariables("logon_user").
At this point, you can log the user on with FormsAuthentication, for example, without requiring them to login again.
You could then either implement the SQL Server Membership Provider or create your own interface to your database for further user validation and extra information storage. We have used both mechanisms, but I prefer the self-built one due to the additional control it provides and, in this case, you won't need a lot of the functionality (password reset, recovery, etc) that the membership provider offers.

How to allow multiple authentication methods in ASP.NET?

I'm building a new ASP.NET MVC application (in C#) and one of the requirements is to create a new database of members. For this, we'd need roles to manage the different types of members and profiles to manage the additional metadata attached to each member. So far so good, just use the standard MembershipProvider, RoleProvider and ProfileProvider provided as part of the .NET Framework.
However, the catch is that I'd like to allow different authentication methods. I'd like Accounts and Login Credentials to have a one-to-many relationship (one account can have a number of login credentials attached). A user for example, might have both an OpenID and ActiveDirectory account attached to their account.
However, after experimenting with a few ways we opted for the MembershipProvider route (explained how it was achieved as an answer below).
My question is, how have people done this before and how would people suggest I approach it? It appears to be something that is achieved on quite a number of sites, yet a search on here doesn't return anything solid to play around with.
EDIT: After looking around for a good period of hours overnight and this morning - I'm still not convincinced that butchering a single MembershipProvider would have been the easiest option. Does having multiple MembershipProviders give the same effect?
BOUNTY EDIT: With no responses, I am assuming that there is no more optimal solution that the one I posted as an answer. Is this really the case? I'm offering a bounty to try and see if anyone has any further thoughts on this and whether there are better alternatives.
BOUNTY ACCEPT EDIT: I think that WIF is the answer as accepted below, for a .NET 4 release and maybe other versions as it probably works with 3.5. Other than that, maybe a butchered MembershipProvider or adapted one may still be relevant.
In my opinion, the "real way" of doing this is to use federation with WIF (Windows Identity Foundation, formerly Geneva framework).
The idea is that you separate authentication from authorization. The authentication is performed by a so-called STS (Security Token Service) and it manages all the possible login mechanism that you want to support. When a user has been authenticated the STS issues a token containing a set of claims and the user's identity.
This token is sent to the web site (called a relying party in this lingo), and the website determines which parts of the site the user has access to based on the claims in the token. WIF supplies both membership and role providers that extract information from token.
You can read about creating a claims aware website here.
One of the pros of this approach is the separation of concerns between authentication and authorization. You do not need any complex membership and roleproviders in your website. Furthermore the STS can be reused to authenticate users to other applications you might have without them having to register more than once (effectively achieving single sign-on)
The downside is that you will have to spend some time studying these concepts and coding your STS. Mind you, it is not hard to code an STS with WIF, but it is not a 100% trivial task either.
If I have managed to tickle your interest I would recommend that you start out by reading this whitepaper.
Kind regards,
Klaus
One idea we've followed is to create a custom Membership / Role / Profile provider. We customised the login / authentication methods significantly and have an additional table of logins. This table basically just contained:
LoginID (Auto-Incremental ID, PK)
UserID (FK)
LoginSystemID (FK)
...blah blah
Within the above, the LoginSystemID was a link to a foreign lookup table which helped the system to determine which authentication service to use (e.g. Standard, AD, OpenID, FacebookConnect - etc).
The problem we ran into was that the Username field in the MembershipProvider couldn't be empty and while in our schema everyone had a UserID (it was their account name), they didn't have a Username that was unique. We had to get around this by generating a GUID and using that. This of course is hidden from the user and a DisplayName attribute from our Users table can be displayed instead.
This was all done via FormsAuthenication (the AD checks were done via LDAP checks). However, an additional layer (a webform) was added with appropriate settings within IIS that provided a means for automatic WindowsAuthentication - we redirect to there in the instance that we feel the user is likely to be internal (based on IP address).
Use standard framework stuff. See http://blogs.teamb.com/craigstuntz/2009/09/09/38390/
You can have an unlimited number of authentication methods attached to one account, the magic is in the FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); statement

Categories