I've got two programs, a "login" program that uses the a foreign STS (Google, Facebook, etc.) to log the user in and returns the type of security access that user has. I then want to send that information off to a separate program that takes that security access and gives the user privileges based on that.
What is the best way to send that information across?
I've read some things about the Custom Authorization Manager Service, but I'm not sure if that is what I need here. Is it possible to just POST the security info across and the web.config turns that into a claim? Should I be making a new token and sending that?
I am hopelessly lost. If someone could provide a helpful tutorial somewhere on the web, that would be immensely appreciated (as my googling has only turned up long-winded articles that either do much more than I need or much less).
Specific code snippets would make my day.
Thanks!
EDIT: I am trying to avoid making the login system into an STS. But I am starting to feel I need to. Is there some halfway point between STS and relying party? Like a relying party that can generate its own claims?
You have several options:
The simplest one is the ClaimsAuthorizationManager, which might be what you're looking for. http://msdn.microsoft.com/en-us/library/ee748497.aspx The CAM is a step in the ASP.NET authentication pipeline that runs right after your application has validated the security token incoming from ACS. Here is where you define your custom authorization logic, and you can add additional claims to the IClaimsPrincipal that gets delivered to yor application. Instead of centralizing authorization logic in a service, you could for example implement your CAM in a library that's shared accross various relying party applications.
If your authorization rules are simple, i.e., you're not querying any external user attribute store, then one option would be to use ACS claims transformation rules to do this. Then your applications would consume the token issued by ACS directly. http://msdn.microsoft.com/en-us/library/gg185955.aspx
If however your architecture absolutely requires a separate login service that consumes tokens and populates new tokens with user attributes and such, then it will need to be an STS. Building your own STS can be tricky, but there are prefabricated STSes available to do this. If your applications live in an AD domain for example, ADFS 2.0 would be an ideal choice because of it's close integration with AD and ACS, and it's powerful claims transformation capabilities.
Related
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.
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.
I've been trying to get my head around SSO in an enterprise environment and what solution best fits my companies problem.
We have several apps (mostly in .net but some in java) running on our domain.. a.mydomain.com, b.mydomain.com etc...
My problem lies in trying to figure out how to implement Single Sign On, because as far as i can see, the likes of OpenID and OpenAuth are used for facebook, twitter, linked in based SSO, ie consumer based SSO.
We want an internal SSO system setup but I cant find many enterprise examples of how to do this and what protocols/frameworks/servers to use.
Can anyone give me an idea how and if OpenID/OpenAuth should be used for this case, and what the benefits and disadvantages are?
also, would token based SSO be a good idea for this? considering all the apps wiill be on the same domain (SSL is setup).
Finally, what about cookie based SSO, is this a good idea?
Thanks
Neil
As you mentioned that all your apps are in the same domain and you are looking for an internal SSO solution I would recommend going for a cookie based SSO service.Simply because
It will be easier to implement. Just checking the cookies and giving the user access to an app.
no XML message exchange between your different apps (no need to design a schema)
You don't need to hire any Web service experts. (As long as your developers know how to handle cookies)
ultimately it will depend on your scalability requirements.
update:
Scalability:
In future you might expand you user-base across different geographic locations.
Your different applications might have different servers and the user database might become distributed.
In such cases you will have to maintain an identity repository to give authentication as a service.(This is what is done by the authentication frameworks that you mentioned)
Cookies:
Cookie handling is no rocket science. The browser automatically sends cookies to
your server in the HTTP request and you just have to read it.
Create the cookie wen user logs in. Set the domain property to your root domain so that
other sub-domains can access it.
Check for cookie when user tries to log into an app. If cookie is present that means the user has already logged in.
Don't forget to delete them when user logs out.
Active Directory Federation Services (http://msdn.microsoft.com/en-us/library/bb897402.aspx) is an enterprise solution. I would not recommend writing your own token issuer as there are lots of risks involved, security and performance.
I've looked to many sources, and found many examples, but none really fit the situation that I hope to take a project to. I am writing a bunch of WCF services, some publicly accessible, others not (server to server), that will allow a fully flexible cloud app that ensures the ability to scale out the service as needed through Azure. I am unsure which way to go with message authentication, as I want to make sure a particular user logged in, can perform different tasks, and prevent others from running those tasks.
Most of what I have seen uses roles or ASP.NET membership. I have my own custom membership users will use to login with, and I don't rely on standard membership providers, or active directory. What is your recommendation? I thought about just creating a token that is created on successful login, that is stored within a cookie, added as a parameter passed into each method, but with some research, I think this might be able to be handled without modifying all my methods.
What are your thoughts?
You can easily implement authentication without needing to manually pass a token into all your functions by using UserNameAuthentication and writing a custom validator - there is a fairly straightforward tutorial here
If you use UserNameAuthentication, you will need to use SSL/HTTPS, which means you'll need to get a server certificate - this is a good idea anyway for most business applications.
At the server side you can get the identity of the current user:
IIdentity wic = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity as IIdentity;
use basic authentication and have the webservice authenticate against your membership store.
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