Best way to secure a silverlight image viewer in a web application? - asp.net

I have a web application that is secured and stores user detail information in a session object. I am building a Silverlight control to view images that are stored in the database and access to those images needs to be secured. I am not trying to prevent copying or anything like that but I need to make sure that the user accessing the image actually has access to view the image which can be achieved by checking the user data in the session.
So my thoughts were to do the following:
Web Application that has hosts the Silverlight control.
A ashx file to handle the serving up of the image from the database.
The ashx file when accessed via the silverlight control will check the session to make sure they do have access to this image. (I am assuming the silverlight control and web app share the same session, this could be a wrong assumption.)
Does this setup sound correct or are there other ways of approaching this? This will be my first time integrating a Silverlight control into a web application.

THe silverlight control lives within the context of the browser. I think that if you're silverlight control callse your ashx page, the ashx page will execute under the same session that your web application is running.
When a user logs into your web application, store something in the session to indicate they are authenticated, and check it in your ashx page.
It is a simple scenario to mockup and test.

Sounds like you want to ensure that nobody is sniffing traffic to determine the URL to your ashx path. Perhaps you don't want that URL being used independently from your page, or for other images that the user/caller shouldn't be seeing.
Have you considered leaving a cookie value for the client? Perhaps a scenario like this:
when your customer visits the page, it sounds like you want to load an image into a Silverlight control. At the time that you're processing the other data on the page, send a cookie value back to the browser.
drop a salted/hashed value in a cookie based on the browser/caller AND the image being requested.
Let's say that the image is someImage.png, and the client's IP address is 10.10.10.10. Use some salt like the image's db identifier to ensure uniqueness between images. Let's pretend it has ID 509.
Run the string "509_someImage.png_10.10.10.10" through a one-way encryption method (i.e. AES) using a strong key that you keep secret on your end. Let's pretend that your result is 'biglongcrazyrandomstring123', but it will obviously be much longer.
on the querystring to the call to the image.ashx page, force the include of that value (i.e. image.ashx?img=someImage.png&key=biglongcrazyrandomstring123).
On the server side, you go to your DB and retrieve the ID for someImage.png. Run the requestor's IP address, the image file name, and the database ID through the same encryption algorithm. Compare THAT value with the value sent in the querystring. If they match, then you know that YOU put the string in their cookie. Rather, you know reasonably that they couldn't have guessed it.
If anyone tries to mess with that querystring value, it'll fail every time because you're comparing two generated values.

Related

add asp.net pages to an asp classic website

I have an asp classic web site and I want to add some new code. I would want to begin to code with .net. Is there an easy way of doing this.
I was thinking an iframe that call my .net pages, but how will I share my user that need to be logged in my asp classic web site.
If I would use an iframe, what would be the best technique to share my user. I was thinking of passing the crypted info in query: test.com?users=[mycrypteduser]. But how would I encrypt it?
I'm pretty sure you can mix aspx and asp files in a single web project. So, create web-proj, then drop your existing website files to it (from within VS). Then, slowly start to refactor your existing site to aspx, as you can, page by page, and create new pages as aspx, of course.
Using IFRAME over this approach will be a lot more work that one may anticipate. But, regardless, you're hitting the problem of 2 unrelated websites in the need to trust each other authenticated sessions - and, this is primarily solved by those websites communicating such information to each other in the background, without the direct involvement of the browser. You need to be able to change the code at both sites (so, you must own both sites). So, if you want to go that route, typically it'd be done this way:
User logs in to your asp site
Your ASP site calls a webservice at your ASP.NET site and informs it that the user will be coming with a particular one-time auth-token in query and that it should be trusted. The emphases here are: the webservice must be well protected by authentication mechanism (otherwise you're risking a huge security issue); the auth-token mentioned should expire after it's used once and only once (otherwise, you're opening your asp.net site for abuse). Typically, your ASP app would call a service at ASP.NET with a signature like this: string GetAuthToken(string username). ASP.NET app should store this info as a record in a database: username, some random and unique string value (e.g. guid), create time (with the precision of at least a second), and time used.
Your ASP app receives a one-time auth token from ASP.NET app.
Your ASP app would need to include this token into the URL used on the frame to a page at ASP.NET site.
Your ASP app would then serve the page with a frame to the browser.
The browser starts displaying the page, then it gets to displaying the frame to external asp.net page
The browser requests the asp.net url, which contains the auth-token
ASP.NET site receives the request and it assumes that the auth token is present and valid; otherwise, exception. Valid token is: never used (time-used in db mentioned in step 2), and valid (its existence in db). As the receiving page validates this token, it immediately checks it off as used. It's the best to put this logic as one atomic operation (e.g. a stored procedure, if you're using MS SQL Server). This way, you can execute both get-token and mark-token-used in a single step. This URL must be anonymous; you must have forms-auth on this site anyways, and this particular handler should be reachable by anon user. If you dislike making that exception, then maybe create an HttpModule, which would inspect every request, and act only on those that are anonymous and are containing the auth-token (by validating the token, and then, as appropriate, interrupting the request or letting it execute); this way, your framed page doesn't have to care about authentication, but it must be forms-auth protected also. I personally would do this that way (http module). Also, if you're sure that relatively short period of time will pass between step 1 and step 2 here (e.g. few seconds max), then do include token expiration in your token-validation logic (validation time must not be later than token-create-time + some number of seconds, e.g. 30) - just for extra security. Otherwise, if you don't implement expiration - imagine a user logging in today, which generates this never-expiring token, and a malicious user somehow getting a hold of the token string. Then, if the authenticated user never visited the page with the asp.net frame, then the token would be usable days, months, years from the moment it's issued, even after the real user closed their account. You don't want this risk. If the login page doesn't redirect to the page with the frame, then make the service call from that page instead (once per session). Ideally, the token should expire 30 seconds or so max after it's created.
If the token is valid, the part of your ASP.NET app that is validating the token would then be responsible for issuing forms-auth cookie. You'll find a ton of examples out there; keywords: FormsAuthentication, create cookie, authenticate user. Make sure that besides inserting the cookie into the response (which is done by default by FormsAuthentication module), you also set the identity of that current/particular request immediately, as until you do, your request is still considered anonymous. If you don't do that (and people do this, but I don't think it's necessary), you will have to redirect that request (which would force the browser to send up the auth-cookie that it just received in the 302 response).
Finally, your framed page receives an ok that the user checks out and that they may view the content that that page generates. Your page streams HTML down to the browser, and the browser shows that content in the frame.
Note that you will not be able to have any sort of client-side scripting (javascript) going on between the page and the frame (security reasons), and that would be another way why I'd rather mix asp with asp.net files (and slowly upgrading the asp part to asp.net), provided that makes sense in other business-related aspects.
Beware of shared-hosting issues related to outbound requests. Some hosts block all outbound traffic; so, if your asp app is in such environment, you won't be able to make that webservice call to asp.net. If you have the asp app making other/unrelated http calls across the internet (e.g. it talks to 3rd-party web services), you're good (it'll work); otherwise, do test this somehow, as you can never be sure. Also, even if your site runs in your own environment, companies often have outbound firewalls in place, so, you might have to request an exception for this.
Remember that the page-refresh will not be an issue, and you do not need to make the get-token call more then once per authenticated session. This is because the browser will, after the first frame load, have an auth-cookie from asp.net site, and the token (even if present in subsequent frame url), will not be validated (remember, the module validates token on anonymous session only; see step 8).
Do think about adjusting cookie expiration settings between the 2 sites. Imagine asp.net auth cookie expiring before the asp auth cookie expires: user reloads the page, and the iframe shows the login page on asp.net - ugly. So, your asp.net auth cookie should probably be set up to expire longer than asp auth cookie (however long you set it as, you won't fix the problem, as it's either wrong to set the cookie to not expire for extremely long time, e.g. 7 days, or it's theoretically possible that a user of your asp site will sit through all that time without touching the page with the frame after they saw it once, and your asp.net cookie will expire). So, do something like this maybe: set asp.net auth cookie to expire in 20/30 minutes (one of those is the default timeout value). Then, have asp app be aware of this timeout value. So, correction to my previous statement of one get-taken call per session. Instead, have the asp call the get-token service every time that you know the asp.net cookie already expired or might expiring soon. In other words, keep track of when you made the last get-token call for each user, and if 15 min (for example, where asp.net cookie expires in 20) has passed since last get-token call, make it again, change the frame url, and the frame will be authenticated once the existing asp.net cookie expires (which would be approx 5 min from that moment, in this example).
I keep coming back to edit this answer :) So, cookie expiration problem - assuming asp.net cookie expires in 20 min, and I told you to set the url on the frame every 15 min, while I also told you to make the token expire in 30 sec - so, those 2 things are conflicting. Hm, I wonder what's the best solution here... Maybe set the get-token to happen closer to asp.net cookie expiration (as in, e.g, at 18 min, but still less than 20), and set the token to be valid for, I don't know, 3 minutes). This would result in 18 + 3 = 21 to overlap the asp.net cookie expiration. All this because the user already has asp.net cookie. So, 18 min after that first cookie was issued, they visit the page with the frame, and the page decides to get another token. This starts token-ticker on asp.net site, and it sets the iframe url with new token. But, since existing asp.net cookie is still valid, the new token will not even be validated (remember the module only validating anon requests with token? Otherwise, you'll have too many db hits if you do it on every request), so the new token will not be used immediately. Eventually, asp.net cookie will expire (in 2 min), and the new token will be validated. If this is a problem (if I omitted some use case that essentially results in the login page displayed within the frame), then maybe you can implement some other mechanism to keep these cookies in place: maybe add code to the login page at asp.net to look for the token in ReturnUrl (decode, then load into NameValueCollection, then look for it as a normal querystring lookup), and maybe communicate back to the asp site something that would signal it to re-request the token when the frame comes back (and what I mean by this, redirect the framed login page, in this case only, back to a special asp script at asp site, which would re-request the token, and then redirect the frame back to asp.net with new token.
I told you it'd be a lot of work. Perhaps there is a standard that involves all this. Check out OAuth (http://oauth.net/) and OpenID (http://openid.net/); those methods are similar to what StackOverflow is offering as login alternate to SO accounts (Google, Yahoo, etc). However, that implies that you actually send the user to the asp.net site to login, then come back to the page that displays content from asp.net site. Perhaps you can combine this with the webservice call that I suggested (get-token ws, redirect top window with token in url to asp.net, asp.net will authenticate and redirect back, then page with frame will display). However, you still have the cookie expiration problem, as you need to constantly be able to get content from asp.net site (whereas, StackOverflow, for example, talks to Google on my behalf only once, during login, and never again during the session), but instead of that messy iframe redirect path that I send you, maybe you can simply repeat the login-to-asp.net-site routine every 15 min (get token, redirect there, validate token, redirect back). If you do this every 15 min at the whole asp site level, you should be fine - and, the user won't even notice this in most cases, as those redirects will be quick.
I'm sorry if this is a difficult read. I hope it helps, though. +1 if it does :)
You can create a new ASP.NET web application, and pull all of your classic ASP pages. Then when you deploy, the ASP.NET web application will overlay your classic ASP.
If you are using some sort of integrated authentication, both the ASP and ASP.NET pages will have access to the same identity. If you created your own authentication layer in the ASP application, you will need to recreate this in ASP.NET (for example, create classes that read/write the same authentication cookies that the ASP pages are using).
However, long term this will introduce some development friction switching between ASP and ASP.NET all the time, so I would really only suggest this approach if you are planning to incrementally convert your entire application from classic ASP to ASP.NET.
You can use NSession http://nsession.codeplex.com/ an open source project with objective to allow ASP Classic to access ASP.NET out-of-process session stores in the same way that ASP.NET accesses them, and thus share the session state with ASP.NET.
I have tried it out and it really works.
Happy Coding!!
When i face this issue, i have found the best solution is usually to use .NET as a web service, and use HTTPRequests in the ASP page to pull the data into your ASP page.
When sharing sessions with ASP and Classic ASP, the most common way is to NOT USE SESSIONS IN ASP, and Use Cookies, Database Cookies actually for the actual session verification, by GUID usually.

ASP.NET A question about safety after writing some data to HtmlControl

I have a hidden input on my form, and my JavaScript code writes there dynamically generated string based on the user behavior on the page.
Later, I access to that inpput via server side code.
Many users will be using this page at the same time, so what about thread safety ?
I mean, could it be possible that userA has an access to that string generated by userB ? Or maybe server will read that string from each user's Web Browser ?
This is all happening at the client side, on each individual user's machine - when they post the data from their machine, you'll get the data created there - there will be no cross pollution.
As far as I remember, there won't be any problem regarding thread safety.
Considering the Server side, when a user visits an asp.net website, he/she is given a different application domain in the server, so I guess there won't be much trouble here.
And about the javascript, it is executing inside the client's browser and machine, so why on earth there will be concurrency problem?

Redirect to a different web application with associated data

I'm building a solution where 2 applications are involved.
One of them handles the login and user management, and and other provides the service itself.
I need a way to send the user from the first app to the second, along with some data that derives from the whole login process.
The data has to be sent in such a way that it can't be tampered with; or a way to check if it's legit has to be available.
Some more details:
The solution consists of 2 ASP.NET (Webforms) websites
Although both websites are sitting on the same server, a solution that doesn't rely on this is prefered
Thanks in advance.
It might not be the best solution.
But this is what immediately comes to my mind.
Serialize the data, (from first website) that you need to pass, into a database accessible from both web sites (can be a third server in worst scenario when your both website might be sitting on different server).
Generate a key for the serialized data in the database. It can be a GUID. Pass it on to the other web site. Other website can delete it immediately after retrieving it by using the give key.
You could set an encrypted token cookie in the login application and pick it up in the management application.
I don't know of any way to transfer state data between applications on the server.
I am not if it is possible to use Server.transfer to the second site. But this would definitely be tamper-proof since it would occur on the server. The landing page on the second side would then persist the transfered info. Context object would be a good location to store the transfered info.
At a minimum it would recquire both apps to be on the same server.

Limiting web service access to a public facing Flex application

I have a flex application which collects data entered by the user and posts it off to a web service I have running on a back end server. The flex application does not authenticate users (it's available for anyone to use without setting up an account) and communicates to the web service using HTTPS.
There is an XML firewall in place for preventing certain malformed requests, DoS attacks etc and the web service validates all data received from the client.
If I was to sign the content then I could use the XML firewall to verify the signature but I assume that any certificate type data I embed in the client could be extracted out of the flex app through some means of de-compilation.
My question is, is there any way of limiting calls to the web service to only those from my flex client? I understand that a user could input bad information but I'm really trying to prevent another client or 'bot'.
If I were to introduce having user accounts to take advantage of a session based solution then presumably I still face the same issue when I'm trying to set up the account in the first place (would have to still be done in the flex app)?
Like TheBrain mentioned, the crossdomain.xml file is where you need to start, but this only keeps other flash based applications away. His idea about the random id is also a good one but I could see that being rather complicated to implement. You could implement user accounts only having those accounts set up through some other means than the flex application (something presumably more secure).
Another way would be to have a shared password between the application and the webservice side, and encrypt that password on both sides using some sort of salt that both sides could know. My first instinct is to think of a time based salt. You could pass the timestamp from the flex application along with the rest of the request and then take your password and the same timestamp concatenated together in someway, hash it and pass that along as well. In the webservice when you get the request, you take the same password (not passed with the request in the clear) and the timestamp that was passed and hash it using the same algorithm. Then compare. If they match then it is an authenticated request. You could even store a dictionary of passwords, and use a different one for each day of the week or something like that. Just however you do it, make sure that your two methods of determining the hashed password is identical. This should provide enough security for most applications. Let me know if any of this needs clarification or if I have misunderstood the question.
After re-reading your question, I see you are worried about decompilation. I don't have an answer for this off the top of my head. You could potentially store the password outside of the application and read it in, but that doesn't solve the problem of the person decompiling to be able to read that file. I will think some more on this and see if I can come up with something to guard against that.
you can add a crossdomain.xml to your server so then only your flex app can access your domain service and...you can generate some random id when you show the webpage and give it to the flex app as a parameter. so when the flex app makes the first service call, the id should be there. with the service response, generate another id and send it back to the flex to use it with the future call and so on.

redirect to another URL issue in ASP.Net

I have two web applications and sometimes I need user to jump from one application to another. Since they are two web applications and may reside on different domains/machines, I can not share session between them.
The technical challenge for me is how to pass session information (I only need to pass userID string information in the session) from one source application to another destination application -- so that the user feels Single Sign On and personal information is displayed for him/her in both application (as the userID is passed to the destination application, no re-login is needed).
My current solution is generate all URL strings in both application and append them with user ID after user logins successfully, like http://www.anotherapplication.com/somepage?userID=someuserID, the userID value is retrieved from session. But I think my solution is stupid and I want to find some way to automatically append the query string ?userID=someuserID when the user jumps to another URL in another application -- so that I just need to generate the common unified URL http://www.anotherapplication.com/somepage in both application.
Is there a solution to automatically append the userID query string?
thanks in advance,
George
Rather than doing it via the Querystring, it might be more maintainable in the long run if you use create a FormsAuthenticationTicket with the required values.
I especially recommend reading Michael Morozov's excellent article on the subject of SSO (Single sign ons).
I do not think it is a good idea to have the user id in query string.
A better idea would be to implement a single-sign on solution. In your scenario, you could do the following:
Whenever one of your applications receive an unauthenticated request, redirect the user back to the other application to a special single-sign-on url.
This page checks whether the user is logged in, and if so, redirects back with an authentication token in querystring.
This token is checked by the un-authenticated application; and if it passes, you can login the user.
Of course, this seems like "a lot" of redirecting, but it should be reliable, and it only happens once, and then your user will be authenticated on both applications.
Obviously you would need to implement a security scheme so that you can check that the authentication token you get passed is really valid and originating from your other application. You could do this with a challenge-response algorithm; which could be:
Both applications should know a common key.
First application sends some random data (the "challenge") to the second application.
The second application includes a hash-value of the random data + it's answer + the secret key in its response.
Now the first application can check that the second application knew the secret key by calculating the same hash-value.
Have a look at:
http://en.wikipedia.org/wiki/Challenge-response_authentication
EDIT:
With regards to session state, see http://msdn.microsoft.com/en-us/library/ms178581.aspx for an overview. It is possible to share session state between the applications, but I would not recommend it in general. If your application resides on different domains (URLs) you would have to use cookieless session state; which is not safe. If you decide to go this way, you would either have to use State server or SQL Server for session persistence, depending on your setup.
You can persist the session using something else than InProc (which is short for in process). If you persist the session using a SQL Server backend you'll be able to retrive the session cross domain/machine if they are setup to use the same SQL Server backend for session storage. This is configurable in ASP.NET and support out-of-the-box. I suggest you look it up.

Resources