I'm using a login form to authenticate users.
FormsAuthentication is right out as it stores sensitive user/role membership in either client-side in a cookie or within the URL. Within the URL is a huge security risk, so I won't even get into that. With the
FormsAuthentication cookie, this creates problems with a) security where the client is in the position of dictating it's own roles; and b) way too much data stored in cookies. Since I'm gaining nothing through security and loosing out big time on the size of user data storage, I'd rather just work with Sessions.
I'd like to reuse something like FormsAuthentication for all its basic login form-handling features. But i would rather have it store user data server-side in perhaps Session rather than client-side all stuffed into a single cookie. I'd rather just authenticate against a Session token of some sort.
I have no database and local disk storage of user data is forbidden. I rely on a 3rd party authentication service provider, and a requirement is that I must reduce chatter with this service. Thus, sessions for temporary storage of user info. Sucks, but that's not necessarily the problem I'm asking about. Also, a requirement is that I must set/use HttpContext.user and likely Thread.CurrentPrincipal for use later on in such things as AuthorizeAttribute, for displaying user info in views, etc.
So FormsAuthentication stores all user data client-side in a cookie. Whereas Session stores all data server-side and just relies on a simple client-side token cookie. However, Session is not available anywhere during the asp.net startup and authentication steps. Is there an equivalent forms "membership" provider that stores all data in Session server-side instead of client-side?
If there is no Session equivalent...
Where do I set HttpContext.user and Thread.CurrentPrincipal to make both values available throughout the rest of both MVC apps without interfering or messing up other MVC components?
Hinging on #1, is Session available at that entry point? If not, how do I make it available so I can create the Principle/Identity object using the data stored in Session?
This can't possibly be a unique requirement. Are there libraries already available which handle this?
Session stores information in a client-side cookie too! (or in the URL if cookieless).
If you want to authenticate a client, he'll have to provide some kind of credentials - usually an encrypted token in a cookie once he has logged on. If not a cookie, then what do you propose?
You should use FormsAuthentication. The sensitive information stored in a client-side cookie is encrypted using a key that should only be known to the web server. "the encryption methods being public knowledge" doesn't mean that you can decrypt the data without access to the appropriate cryptographic key.
You mention "roles" and a "third-party authentication provider". If your third party is also providing roles (i.e. an "authorization provider" as well as an "authentication provider"), then it would be reasonable to cache roles obtained from the provider on the server. Session is not available when a request is being authorized, so the best solution is to use the Cache (System.Web.Caching.Cache).
Personally I would encapsulate this in a custom RoleProvider. The custom RoleProvider would implement GetRolesForUser by getting roles from the third party on the first call, then caching them in Cache.
Not sure if I like what I'm about to suggest, but you could do the following:
Leverage the Application State or System.Cache as a global storage for user credentials.
Use an InMemory database (like RavenDb) which can also have encryption (in memory, I believe).
Using the Application state as a place to storage relatively common / frequent stuff I think is not a great place because of
Scaling / locking issues? <-- just a gut feeling.
Permenant data? so you have users in the website's memory .. then the website crashes or recycles, etc... what happens now to that data?
RavenDb is awesomeballs - go.use.it.now.
I understand that you are not storing anything locally, so whenever a user hits your system, you need to refresh your inmemory cache, etc. Fine. A pain in the f'ing butt , but fine none-the-less. (EDIT: unless the data has been cached in memory .. that is)
Anywys, two suggestions.
ProTip:
Oh! move away from role based shiz and start using Claims based identity stuff. Yes, it still works with IPrincipal and HttpContext.User, etc. So all previous code is NOT busted. But now it's baked into .NET 4.5
Awesome Video on this for you, me, everyone!
Finally - bonus suggestion
A nice package that auth's with either Facebook/Google/Twitter. You said you're keeping the user cred's on another site (good move!). If you're using other providers, then stick with DNOA or SS.
GL!
Related
I'm looking into storing some security sensitive information (a users effective permissions for our web application) in a session-resident object, to reduce database queries while performing permissions checks throughout the app.
I understand that the session is stored server-side, and not directly accessible to the client under normal circumstances. ASP.net's other persistence mechanisms can be theoretically defeated, by modifying viewstate or cookie values client-side, but these kinds of cryptography implementation flaws should not expose session-state.
What degree of control over your server would an attacker need to modify data in a clients session-state? Assume they have a sessionID, and an ASPAUTH cookie.
For instance:
A remote attack, like a modified POST or other handler call to a
page?
Would an attacker with programmatic access to IIS (WMI mabey?)
be able to access and change session-state in the same or another app pool's memory?
Would an attacker need to be able to post code to my app, in order to manipulate session memory?
I know these kinds of questions often rely on mistakes in my code, so by all means assume I've written the worst, most insecure code ever (I haven't, but...) and do things like change session in a constructor or life cycle event.
Since we don't know exactly how your code is implemented, all we can do is guess.
First, Session should NEVER be used for security sensitive things. Yes, it's true that a client can't directly read session, there are other factors to consider.
Session cookies are not, by default, encrypted and are passed as plain text.
Session Fixation attacks are easy to accomplish
If a session cookie is hijacked, or even guessed, then it doesn't matter what the users account is, they will get whatever security rights you assign via that cookie.
Session is unstable, and IIS can kill sessions whenever it feels like, so you end up with the situation where a user is still logged in, but their session is lost due to many possible reasons. So now their security is also unstable.
There are many other, more appropriate ways to do what you want, Session is NEVER an appropriate method.
Other methods that would be appropriate include...
Using the user data field of a FormsAuthentication ticket to store the information
Using a custom Claim with a claims based authentication, like ASP.NET Identity, WIF, or IdentityServer.
Using the asp.net Cache to hold the temporary information, based on identity (not session) and adding a cache eviction timeout.
and many more...
Session variable can be a security risk. It is always better to secure your session variable.
Few links you should take into consideration...
Securing Session State
http://msdn.microsoft.com/en-us/library/ms178201%28v=vs.140%29.aspx
http://www.dotnetnoob.com/2013/07/ramping-up-aspnet-session-security.html
http://www.codeproject.com/Articles/210993/Session-Fixation-vulnerability-in-ASP-NET
http://www.dotnetfunda.com/articles/show/730/session-security-in-aspnet
I agree with Erik views.
regards
Everything I've read about claims-based authentication is essentially about "outsourcing" your authentication process to a trusted 3rd party.
See:
Explain "claims-based authentication" to a 5-year-old
Why Claim based authentication instead of role based authentication
Obviously this lends itself well to using something like Facebook or Google to authenticate. But what if there is no 3rd party? What if you just need users to authenticate against an internal database? For example, in a corporate setting. Is there any reason to use claims over plain old roles? If so, some concrete examples would be helpful.
What I know about claims so far:
I understand that claims are key/value pairs rather than booleans like roles.
I understand that claims can store roles.
And if I understand correctly, claims get stored in an authentication cookie (maybe this is key - fewer database calls vs. roles?).
There are numerous reasons, including these you mentioned.
Another reason is that forms authentication module is incapable of handling too large cookies. Just add few hundred roles and exceed the maximum allowed cookie size (4kb) and you are out of luck. The session authentication module that handles claim cookies automatically splits too large tokens into multiple cookies. And if you don't want to have multiple cookies, just a simple switch to "session mode" automatically stores the large token in the session container and the cookie only contains a small bit of information to reflect that.
Yet another argument for the claim-driven cookie is that you can handle any custom data, including tenant name (in a multitenant application), name of home organisation, age, whatever you can need somewhere later. Forms cookie has the custom data section but it is just a string so that you need a custom serializer to have structured data here.
All this is done by the session authentication module and, frankly, it outperforms the forms module easily then. Switching your forms authentication to the new module is also easy, I've blogged on that some time ago (other people blog about it also):
http://www.wiktorzychla.com/2012/09/forms-authentication-revisited.html
I want to create a authorization mechanism for an application based on WebAPI and AngularJs.
I've seen some articles, which use BasicHttpAuthentication, but i really don't like the whole idea of sending username, and password on every request. The more it doesn't fit for me is because i want to use OpenId authentication, where you don't have username/password pair.
I'm thinking about a solution, but I don't really know how to implement it. The concept is that user is authenticated as in an usual Web application - posts a form with user / password or selects an OpenId provider. If the user is authenticated succesfully, it is placed in a static object, which stores the User object for a certain ammount of time. Next a usertoken is generated and passed to the Client Application. The client passes the token on each request to the server, if the user exists in the above mentioned static object with the appropriate authentication token it is authorized to get the data.
Firstly - Do you think this is a good approach to the problem?
Secondly - How should I pass the authentication token, WITHOUT using cookies? I guess it should sit in the request headers, like in BasicHttpAuthentication but, I really dont' know how to handle it.
BasicHttpAuthentication
I'm with you on feeling dirty about caching the username and password on the client and forever transferring it with every request. Another aspect of Basic authentication that might work against you is the lack of sign-off. Other than changing the password, you can't "invalidate" a basic authentication session. Tokens on the other hand, will typically offer an expiration date, and if you want server-side invalidation you can check the issue date and say "any tokens older than issue date xyz are invalid".
Server State
You mention "If the user is authenticated successfully, it is placed in a static object". But this is independent of the token? This sounds like you're wanting to implement server state management of authentication sessions, but this isn't strictly necessary. The token itself should be sufficient for user authentication, managing server state is another potential obstacle. Server state can become difficult to manage when you factor app-pool recycles or web-farm environments (what if you want two services to share the same authentication token, but not require communication with a central "authentication server" for storing the state / session?)
Passing Authentication Token
Headers is definitely a good place for it. Really, where else is there? Cookies, Headers, Message. Other than a browser client, cookies don't make a lot of sense, and including it in the message can muddy your message formatting a bit, so headers is the only remaining option that makes much sense in my view.
Client Implementation
You've not specified, but I suspect you're interested in calling the service from .NET? In which case System.Net.Http.HttpClient could be your friend. In particular, the DefaultRequestHeaders collection. You can use this to add a custom header to store your authentication token.
Server Implementation
When researching ASP.NET authentication recently, I learned a lot about customisation by examining the Mixed Authentication Disposition ASP.NET Module (MADAM). I wasn't interested in using MADAM as-is, but learning about it from that article and examining the source code gave me a lot of ideas of how I could insert my own authentication module into the web stack.
Hey folks, I would like to know is there any way i can maintain stuffs like log-in,log-out,user-session..etc without using membership in ASP.NET MVC?
Faraaz.
There are three provider models concerned with the areas that you are referring to.
The MembershipProvider is concerned with authentication, validating users and storing data related to the user such as last login date, username, etc.
The RoleProvider is concerned with authorising users for particular areas of your application.
The SessionStateProvider is concerned with storing session for your application.
You can write your own custom provider for any of them if the default providers are not suitable. You could roll your own authentication, authorisation, or session management without the providers, however there would be quite a bit of work involved more so than implementing your own custom provider.
You can use the Session object to store session scoped data.
But for authentication/authorization you will need to come up with your own scheme.
You need to use the Session dictionary and a session state server. See http://msdn.microsoft.com/en-us/library/ms178581.aspx for more info.
Word of warning: In my experience the InProc session state mode only preserves the values you put into Session for the lifetime of the current HTTP request. They don't persist across requests as you might expect, even when you're using a single HTTP server and you'd think in-memory storage would persist. This may only occur while debugging using the built-in http server in VS2010, but even so it can cause you a lot of trouble trying to understand why state information isn't being saved.
I'm porting an ASP.NET application to MVC and need to store two items relating to an authenitcated user: a list of roles and a list of visible item IDs, to determine what the user can or cannot see.
We've used WSE with a web service in the past and this made things unbelievably complex and impossible to debug properly. Now we're ditching the web service I was looking foward to drastically simplifying the solution simply to store these things in the session. A colleague suggested using the roles and membership providers but on looking into this I've found a number of problems:
a) It suffers from similar but different problems to WSE in that it has to be used in a very constrained way maing it tricky even to write tests;
b) The only caching option for the RolesProvider is based on cookies which we've rejected on security grounds;
c) It introduces no end of complications and extra unwanted baggage;
All we want to do, in a nutshell, is store two string variables in a user's session or something equivalent in a secure way and refer to them when we need to. What seems to be a ten minute job has so far taken several days of investigation and to compound the problem we have now discovered that session IDs can apparently be faked, see
http://blogs.sans.org/appsecstreetfighter/2009/06/14/session-attacks-and-aspnet-part-1/
I'm left thinking there is no easy way to do this very simple job, but I find that impossible to believe.
Could anyone:
a) provide simple information on how to make ASP.NET MVC sessions secure as I always believed they were?
b) suggest another simple way to store these two string variables for a logged in user's roles etc. without having to replace one complex nightmare with another as described above?
Thank you.
Storing the user's role information in a server-side session is safe providing a session cannot be hijacked. Restating this more broadly, it does not matter where user role info is stored if an authenticated session is hijacked.
I advise not putting too much faith in the article you linked to, but the 2002 vintage report linked to from your link is of interest. Here are my take-aways:
Don't accept session IDs embedded in URLs.
Focus your time on eliminating cross site scripting dangers i.e. scan all user supplied data and parse out executable java script.
Issue cookies for complete domains (e.g. myapp.mydomain.com)
Host your domain at a high class DNS operator e.g. one that only allows DNS changes from a preset remote IP address.
Don't issue persistent session cookies.
Reissue a session cookie if someone arrives at a login page with a sessionID already associated with an authenticated session.
Better still, always issue a new session cookie on successful authentication and abandon the prior session. (Can this be configured in IIS?)
The only way to make a secure cinnection is to use SSL. Anything less than that, and you simply have to make the evaluation when it's "safe enough".
A session variable works fine for storing a value, with the exception that the web server may be recycled now and then, which will cause the session to be lost. When that happens you would have to re-authenticate the user and set the session variable again.
The session variable itself is completely safe in the sense that it never leaves the server unless you specifically copy it to a response.
Have you considered setting up a custom Authorize tag in MVC. I gave an example of this in another question.
On initial authorization (sign-in screen or session start) you could seed a session value with the IP address also. Then in your custom authorization, you could also verify that IP's still match up as well. This will help make sure that someone isn't 'stealing' the person's session. Everytime you access your session data just make sure to pass the requester's IP and have some check on it.
Are you trying to control the access to functions at the client level? That is the only reason I would expose the roles and items to control client side functions.
Alternatively, you could create a function to obtain the items that the roles of the user are allowed to use, and then even if the function is called outside of the items given back to the web application, you can prevent the user from accessing them.
4Guys seems to show how to control functions with the roles.
The approach I have used in the past is to use symmetric encryption of a cookie alongside SSL. Encrypt the user information in the reponse and decrypt it in the request. I'm not claiming this is foolproof or 100% secure and I wouldn't want to do this on a banking application, but it is good enough for many purposes.
The main issue with session variables is that if you store them inProc rather than persisting them, then you need to apply 'sticky' sessions to your load balancing in a web farm environment. Guffa is correct that without this persistence session variables will occasionally be lost causing a poor user experience.
Sticky sessions can lead to uneven load balancing, perhaps reducing the value of being able to scale out.
If you are going to be be persisting the sessions so they can be accessed by all servers in your web farm, you may be better off using a Guid to identify the user, encrypting this in a cookie and retrieving the user record from your data store each time.
My obvious question is that why do you want to store a users role in session ?
Here is my answer to your query, how this helps. I have attached a small demo application for you to take a look at and understand my points. When you open this project in visual studio, click on the project tab on the top and select asp.net configuration. From the page that will show up you can do the user administration stuff.
You need to store the roles of a user in some secure manner ? The answer to this question is that there is no need for you to worry about storing the role for any user, when we have the asp.net membership, profiles and roles framework to help us out on this. All you need to do is create a role in the aspnet database and assign that role to the user.
Next you want to store two string in some secure manner. I suggest you user profile for storing user specific information. This way you have the information available to you where ever you want from the profilecommon class.
Also please see the attached demo application placed at the end of my blog http://blogs.bootcampedu.com/blog/post/Reply-to-httpstackoverflowcomquestions1672007user-roles-why-not-store-in-session.aspx
Just a suggestion, you might consider using this little library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It has a server side implementation of the cookie whereby all cookies can be stored on the server while asp.net authentification is used to identify the user. It supports encryption and is also very flexible making it very easy to switch from one storage type to another.