I would like to hear some opinions about using the isolated storage in Silverlight for storing sensitive data. For example, is it OK to store an authentication token (some GUID that identifies a server-side session) in this storage, or is it better to use cookies?
The isolated storage gives an advantage over cookies in that it is shared across browsers, but it might be more difficult to handle expiry, and there might be some other issues (security?) that I am not aware of.
So... what are your opinions? Or do you know any great articles about the topic?
Thanks, Jacob
I've just started on a Silverlight project that uses Isolated Storage to store a login token that formerly was stored in a cookie when the app was written in ASP.NET.
The only thing I noticed with the end result was that each type of browser would remember the same user (as opposed to the cookie solution where every browser had it's own cookie store and it's own idea of who was logged in).
Security is not going to be substantially different - if you feel inclined to - encrypt the token. Though really why would you bother? If any process has access to a person's private AppData they're going to have access to all sorts of confidential information.
The app's url determines access, so no one can get at the data unless your domain name expires.
Other than the advantage of sharing the token across multiple browser instances, which I personally haven't ever seen the need for, I think I'll stick to using cookies for now. Why? Because they are better supported by intermediaries like proxy servers and HTTP accelerators. In general I adopt a "use the standard" rather than a "roll your own" approach - it results in less code to maintain and more familiar code for new developers.
Related
I wanted to try this code/solution to my ASP.net (VScode 1.69.1) but I am not sure where is the "Global.asax". Anyone know how I can apply the code below to asp.net core?
https://teknohippy.net/2008/08/21/stopping-aspnet-concurrent-logins/
I would not advise you to use that code, it wasn't even good advice back in 2015, but we can explore the concept and it's flaws which might help you come to a better overall solution.
This post will provide some context to the issue: Single Instance Login Implementation but is not a direct duplicate. The original source article does actually go into better detail about the general issues with this approach: http://www.nullskull.com/articles/20030418.asp
Using an In-Memory cache is not a viable option for production as multiple instances of the application would not share the same cache, especially if the application is hosted across multiple servers or serverless infrastructure that is configured to scale out beyond a single instance.
If all you want to do is block new logins, if the user is already logged in, then a server-based or cache concept itself is the right solution, conceptually to enforce a single instance across different browser sessions and across multiple servers will require that there is a server-side cache or store that holds the source of truth for all active connections. This could be in the form of a database or a distributed cache like REDIS.
But this is not a practical model for how users actually use their browsers and devices. Instead of blocking new logins, it is more practical from a user point of view to expire or force close the existing logins. The problem with only blocking new logins is that if the user doesn't have access to the original browser session that holds the login, then there is no way to log out the previous session, you would have to wait for it to timeout. The challenge with being able to expire a login session is that your clients and the server code must be designed to round-trip to the session store to validate the session token. Most default JWT or even cookie implementations do not do this, they will rely on the expiry or validity information in the token itself, and bypass consulting the store.
Instead of the article you have found, please try these resources:
ASP.NET Core security topics
Can I force a logout or expiration of a JWT token?
JSON Web Tokens (JWT) are Dangerous for User Sessions—Here’s a Solution
The question is really that how can an auth server that serves JWT be used by multiple websites of same company or domain (with the websites as sub-domains), for example? Not something for the public.
Already, I'm thinking of asymmetric JWT. Also, I don't want to implement OAuth 2.0 in order to avoid complexity and because the auth server would only serve web apps that are sub-domains of a same root domain.
seeking for less complex solutions based on the current description in this post
If you want a reliable and secure way to share resources between different sites, you might want to look at IdentityServer.
In a nutshell, you basically redirect anonymous user to identity server to login. After successful login, it will return a token to the user. Then the user uses that token to access resources from different sites.
Look at the basic workflow and screenshots at my GitHub sample project.
Ok so here is the deal.
Can multiple web apps access the same database (identity db or otherwise)? Of course! Now if you are using Entity Framework (and I assume you are though it wasn't stated) then this can get tricky as far as migrations etc. Personally I use Dapper so I never have to worry about that :-)
Yes the apps can each access the db but that is WAY different from from SingleSignOn which is really what you are talking about. You want a user to log in to one site and that identity to persist to other completely different sites. That's not nearly as simple as simply accessing a db. IdentityServer is virtually the standard for this kind of thing for many reasons.
No, the ajax approach will not work because when the user logs in at site1 the cookies are for site1. If he goes to site2 the browser does not have any cookies associated with site2 even though you sent credentials via ajax. The user was on site1 when this all happened so all cookies are site1 cookies, totally separate from site2 cookies. Even if you can find a way to make this work it would pose a serious security risk.
You could conceivably do something like this using hidden IFrames instead of ajax because you can set the iframe's site's cookies while you are there. But I don't recommend you do this as there are security risks involved.
You need to separate the idea of "Authentication" from the ideas of "Authorization" and even "User Management".
Authentication---- Am I who I say I am? (check my usename and password and maybe even additional form like text message etc)
Authorization---- Ok you know who I am, but what can I do on your site? This can vary from site to site. Maybe I am an admin on one of your sites but just a regular user on another. My individual site cookies will includes roles etc and they are different for each site.
User Management---- Can I change my name/email/etc?
The best way to handle this is to use a separate server app running IdentityServer. This handles the authentication and builds out the cookies for all of your sites at once. Ideally you should also use this for any user management but that can be a pain and isn't as vital. Here are a few sample apps for IdentityServer4.
Response to your Update 2----
Not exactly... Here is the basic flow: User goes to site1 and clicks "login". This fires a "challenge" which redirects them to website-auth. On website-auth the use submits their credentials (username/pw) via form post. This logs them in to the website-auth but then also redirects the user back to the original calling app (site1 in this case) with everything they need. Let's say the user now goes to site2, they are already logged in!!! Using IdentityServer4, the user will become logged in to all of the sites sorta automatically. You won't have to do extra stuff they way you described, just plug in the necessary stuff and let IdentityServer4 handle the rest.
Look, I understand that IdentityServer4 probably looks a bit intimidating, it did to me until I began working with it. Truth is, all of the hard stuff is handled for you. There is still a decent amount of configuration involved in getting it set up but it really is the best solution for what you are looking for.
Check out these quickstarts: https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts
Response to Update3------
I understand the concern of relying on a third party and how that can seem like a questionable practice, especially when it comes to security. My response is this:
These guys are the EXPERTS in the field. So much so that IdentityServer has become the defacto security solution even in the basic templates Macrosoft provides.
Any home grown solution you will come up with will have more security holes that what IdentityServer has. This is not a slight on you at all. These guys know what they are doing. They have been doing it for years.
Why reinvent the wheel? You will spend 10x (at least) as many man-hours trying to come up with an alternative that, in the end, will still not be as good.
If what you were doing was a single website cookie based authentication then using identity really isn't necessary. Identity can do that, but there are other simple alternatives. But when it comes to multiple sites and SSO, and I really can't emphasize this enough, IdentityServer is the way to go.
The answer is a microservices auth serve that generates RSA/Asymmetric JWTs with a private key and the other servers each have the same counterpart public key to validate the JWT and retrieve the user claims.
But that solution doesn't not cater to the situation where each of those other servers need a different set of claims about about a user.
It is also not a single sign-on approach. So, I'll be back.
But OAuth 2.0 seems to be the answer, but it is too complex for my liking.
I'm re-writing a website from the ground up for azure. Each user has ownership of a number of objects, and has a number of permissions. Together, these determine what they are authorized to do. The question is, how should this information be stored. I want to do the authentication myself, using custom logic.
For performance reasons, I'd like to cache these authorization lists for each user once they're logged in. Can someone give me a sample for how to store & access this session information securely and efficiently.
Edit
I looked into the App Fabric Access Control, but that seemed overkill as I was going to have to create a separate site for authentication, which doesn't seem to make sense. Would the claims based authentication make sense separately though? How would you do that if it does?
Would it make more sense to just keep the username in a cookie in the traditional way and then re-query table storage with each request to get the permissions etc.? How would storing the username work in Azure?
Cost is a big factor here as it's a very small site (by azure standards) but I want high performance for a small number of users.
If you want to run with a reasonable amount of availability you need to run your site with two instances. If you're running with two instances you need to use a session provider that's no the default InProc one. Your choices are:
AppFabric Caching (which you don't want to use because it's too expensive, fair enough)
Azure Storage Session Provider. Don't use this. It's an interesting experiment, but it's only sample code, it's slow and doesn't cope well in production.
SQL Server session provider.
If the permissions for a user weren't going to change while they were logged in, you could just store their permissions in session. This will probably be fast enough. However this information will need to be read from SQL for each request that uses session and it is overhead.
If you wanted to make things faster you could just store the user ID in session and load the permissions into a static dictionary (keyed on user ID) when needed. These items will need to be expired after a certain amount of time or lack of use.
Well, you could use the Azure App Fabric cache to store the session info. ASP.Net can be configured to use it as the backing store for its session state as like a normal custom session state provider.
This article from MSDN shows you how to configure it:
http://msdn.microsoft.com/en-us/library/windowsazure/gg278339.aspx
From your code you just use the normal ASP.Net way to get/set the state.
Be aware though - it could be expensive ($45/month for 128MB of cache).
What I am looking for is way / design to track a user / site visitor without the need for cookies or JavaScript as about 5% of users have one or both of these turned off.
What I would like to achieve is a unique reference for the user which can be captured server side in code.
I was thinking machine CPU / Motherboard ID but this information is hidden.
What information could you use / combine to create a unique hash.
I also need that ID to work across different sessions. Or maybe if the information is unique enough a way to do cookies/cookie type things across different browsers.
You could put a code in the url, this is how cookieless sessions used to work (maybe still do).
UPDATE: taking comment on, depending on your application and number of users you could consider giving each user a dedicated sub domain, or if subdomains are too tricky build it as part of their url. This depends on whether they need to login into the site.
You could look at doing something with client ip addresses but this would not work for everyone.
Are you sure the users really have Cookies switched off? It could be that users have persistent cookies switched off (the ones that write a file to the user's hard drive) and still have browser session cookies switched on. Browser Session cookies live in memory and disappear when the user closes their web browser, but normally this is enough for server-side Session State to work properly.
In nearly all cases where clients have cookies disabled, it's always persistent cookies only. The in-memory ones are still enabled and work fine, you can still track users, but only for as long as the browser remains open, this might be enough for you I don't know.
Update: I just noticed you said this needs to persist across sessions (as in user closing browser down and going back to site later). Have you looked at HTML5 storage options (LocalStorage in particular), it's a simple Key/Value store, and it's reasonably supported across browsers even versions of Internet Explorer.
After some more research aided by Rup and the ret of the comments on here, it has become apparent that there isn't a simple way to track a user across your site without cookies, But its not impossible.
Looks like the only way to truly achieve this is via browser finger printing, using all the information supplied back to the server to make a unique finger print of the users browser, this seams to work for about 95% about the same as cookies.
Browser finger printing at the moment seams like a workable approach but I feel there might be quite a large backlash from the general public / privacy groups if you where to go down this route.
For the moment it seems we are stuck with cookies.
I was wondering if there is a straightforward way of getting a user's session cookie and posting it to a page on a different site to be processed there?
If a diffrent site means a diffrent domain or even subdomain, the answer is no. For security reasons a cookie should not be read by other pages. And as a session cookie only contains a session ID but the actual session data is stored on the server, posting a users cookie to another site would not give you access to the users data on this page.
If example.com sets a cookie, then a page from example.com can have some script that reads the cookie and posts that information to whatever site it wants. So if the cookie is 'under your control', you can send it where ever. Generally, however, a session ID isn't useful except on the site where it came from (and it's probably a security hole that should be fixed if the cookie can leak information about the session). Actually, it's probably a security hole if your pages are giving out your session cookies to other sites.
However, browser security rules will (or at least should) prevent your page from trying to read cookies set by other sites.
Straight answer, if they are different domains, then no. If they are on the same domain, then set the cookie path to "\" and you should be set. In any case, I think it's still worthwhile to check out a technique called web beaconing and see if you can adapt any part of that method to suit your needs, should you be dealing with different domains (hope not).
http://en.wikipedia.org/wiki/Web_bug
http://www.webmaster-talk.com/javascript-forum/183163-redirect-different-page-if-no-cookie.html
This will help u..
Like Kau-Boy said:
If a diffrent site means a diffrent domain or even subdomain, the answer is no.
This is due to the SSH Secure Shell. To do it, you would be going against everything (almost) that the SSH Secure Shell does for the internet. You would have to play with some low level protocols to get all the private keys and such. If these were your servers, this might be possible; but very bug prone because these handshakes (like most) are designed to not happen the same way twice.
In a nut shell: very hard, chances of actually pulling it off: low ... what are you waiting for?