Evernote Resource URLs - google-app-engine

I'm writing an application that takes a user's Evernote notes and displays them in a website inline. By its very nature, people accessing the resources attached to a note will not be logged in. I'm looking at the bottom of this page and saw how to pass authentication credentials via POST and get the resource. This is exactly what I need.
My question is how does this work in the real world? If I pass authentication tokens to the Javascript client (not secure in the first place), I can't get the resource because of Access-Control-Allow-Origin restrictions. The only other way I can think of doing this is saving all of the resources to my server and serving them from there, but that's not ideal (Google App Engine).
Ideas?

Yea, Evernote does not support CORS yet. You can do it in a chrome extension or get it on the server side.

Related

Securing a Google App Engine service deployed in Node/Java against a scripting attack

I have an app engine service deployed in GAE (written in Node) to accept a series of click stream events from my website. The data is pushed as an CORS ajax call. I think, since the POST request can be seen in browser through the developer tools, somebody can use the app engine URL to post similar data from the browser console.( like in firefox, we can resend the URL. Chrome also has this features i guess)
A few options I see here is,
Use the firewall setting to allow only my domain to send data to the GAE.
This can still fail me since the requests can be made from the browser console repetitively)
Use a WAF ( Web Application Firewall) as a proxy to create some custom rule.
What should be my approach to secure my GAE service?
I don't think the #1 approach would actually work for you: if the post requests are visible in the browser's development tools it means they're actually made by the client, not by your website, so you can't actually use firewall rules to secure them.
Since requests are coming into the service after fundamentally originating on your own website/app (where I imagine the clicks in the mentioned sequences happen) I'd place the sanity check inside that website/app (where you already have a lot more context info available to make decisions) rather than in the service itself (where, at best, you'd have to go through loops to discover/restore the original context required to make intelligent decisions). Of course, this assumes that the website/app is not a static/dumb site and has some level of intelligence.
For example, for the case using browser development tools for replaying post requests you described - the website app could have some 'executed' flag attached to the respective request, set on the first invocation (when the external service is also triggered) and could thus simply reject any subsequent cloned/copy of the request.
With the above in place I'd then replace sending the service request from the client. Instead I'd use your website/app to create and make the service request instead, after passing through the above-mentioned sanity checks. This is almost trivial to secure with simple firewall rules - valid requests can only come in from your website/app, not from the clients. I suspect this is closer to what you had in mind when you listed the #1 approach.

Access Google Cloud Storage from web application, always 403

I am work on a web application as an interface with Google Cloud Storage(GCS).
I am using a backend service to retrieve the list of files I stored on GCS and their URL with the JSON API and return that to my web application. However, I was not really able to load the files through those URL, which always came back with 403 forbidden.
I am not sure how GCS authentication work behind the scene and whether it is possible to directly grant access to web application. I am not sure how could I attach application authentication information via http request. What I know is I can do that via the backend service but for the reason of simplicity I wonder if it is possible to get around with that. One of the thing I tried is adding the web application domain(which will be sent via referrer in http request) into ACL to that bucket, which doesn't work at all.
And thanks to what #Brandon pointed out below. I am ok to grant anyone whoever have access to the application to view the content of the GCS since it is an internal app and I have already checked their authentication when I first serve the web application.
====
Solution
I ended up using the signedUrl that expire in 5 minutes and I highly recommend interact with gcs using gcloud (Their python document is really good). Thanks again for the thorough answer!
You have a user on a web browser who wants to download an object that only your application's service account has read access for. You have a few options:
Expand access: make these object publicly readable. Probably not the best choice if this info is sensitive, but if it's not, this is the easiest solution.
Give your app's credentials to the user so that they can authenticate as your app. This is a REALLY bad idea, and I probably shouldn't even list it here.
When a user wants to download a file, have them ask your app for it, and then have your app fetch the file and stream its contents to the user. This is the easiest solution for the client-side code, but it makes your app responsible for streaming file contents, which isn't really great.
When a user wants to download a file, have them ask your app for permission, and reply to them with some sort of token they can use to fetch the data directly from GCS.
#4 is what you want. Your users will ask your app for a file, your app will decide whether they are allowed to access that file via whatever you're doing (passwords? IP checks? Cookies? Whatever.) Then, your app will respond with a URL the user can use to fetch the file directly from GCS.
This URL is called a "signed URL." Your app uses its own private key to add a signature to a URL that indicates which object may be downloaded by the bearer and for long the URL is valid. The procedure for signing URLs is somewhat tricky, but fortunately the gcloud storage libraries have helper functions that can generate them.

Google Analytics with Silverlight HTTPS cross domain policy problems

I'm sending simple messages to Google Analytics from a Silverlight app. They look something like this (data changed):
http://www.google-analytics.com/collect?v=1&tid=foobar&cid=foobar&t=pageview&dp=foobar&dt=foobar
Very simple API. If I use HTTP it works beautifully.
If I use HTTPS, I run afoul of Silverlight's cross domain policies. According to the docs, google-analytics.com needs to approve the cross-domain call by hosting either a clientaccesspolicy.xml (Silverlight-specific) or crossdomain.xml (original used by FLASH). Turns out they do host crossdomain.xml, and I can see that Silverlight downloads it (via Fiddler), but apparently Silverlight doesn't like the file's content and doesn't allow HTTPS calls to that domain (System.Security.SecurityException).
So.. at least at the moment, I can't use Google Analytics from Silverlight using HTTPS. Does anyone know a work around for this issue?
Note, I can't just use HTTP, because that causes IE to issue a "Allow Mixed Content" prompt which causes problems for some of our customers. I need to use HTTPS like the rest of our app.
EDIT: OK, I took a totally different approach, using HtmlPage.Window.Invoke to call a 3 line Javascript function to do the asynchronous send rather than using WebClient in the Silverlight code. Works like a champ. Anybody see any potential problems with that?
I suspect there may be a way to make this work, because I know google-analytics.com is very cross-domain friendly for exactly this reason.
If you absolutely can't get it to work another option would be to proxy the hits. If you do this, you'll want to make sure to use the ua and uip override fields in the hit you're sending so that they show up in Google Analytics with the IP address and User Agent of the original visitor and not your server.
Here's some more info on using a proxy server with the Measurement Protocol:
https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#using-a-proxy-server

How can data be routed thru an app-engine domain if the request is from a page on a users computer?

I have an application on google app engine that serves an html file with the following script
<script>
ChemDoodle.iChemLabs.getMoleculeFromDatabase('pubchem', 'morphine', function(mol){
alertMolecule(mol);
});
</script>
This uses a XHR level 2 request, which requires that iChemLabs (or whoever the server side people are) enable support for my domain. What is the domain that the server side (with XHR enabled) should enable? I don't really understand how data can be routed through the app engine domain if the request is coming from an html page sitting on an app-user's computer?
I think you are talking about Cross-Origin Resource Sharing (CORS) which is method that web servers can use to let the browser know which sites (identified by domain) can share information with each other.
Mozilla has a good detailed run through of how it should work. It relatively new and only modern browsers implement it.
Nothing is "routed through" anybodies apps, all you are doing is telling the browser that sitea.com is happy to share data and accept requests that originated from an application originally served by siteb.com

Many Custom Domains for AppEngine Instance

For our e-commerce service running on AppEngine we would like to offer the option for customers to run the stores on their custom domains (eg: www.mystore.com instead of www.enstore.com/mystore).
From a user perspective, I'd like them to enter the domain name they want to use in their preference screen and tell them how to configure their dns.
I know how you normally add domains to an AppEngine instance (through Google Apps) but I'm not sure you can automate that. And even if that's possible they would be all (hundreds) listed on our google apps page.
Anyone know if this is possible/if there is a good way to do it?
I don't think there is a way to add domains "programatically" to an AppEngine instance. Apparently, domains can only be added by using the Google Apps method that you described. This is confirmed in this SO post: How do i get foo.somedomain.com get handled by myapp.appspot.com/foo on appengine
The only options that pop to mind are the following:
HTTP Redirection
Many DNS providers support HTTP Redirection. In this case, your clients would be able to set up mystore.com and www.mystore.com to redirect to www.enstore.com/mystore. There are some obvious disadvantages with this method that might not be acceptable. First of all, with 301 and 302 redirects, the users will still be forwarded to the registered AppEngine URL: www.enstore.com/mystore, and it will show in their browser. In addition, choosing between a 301 and 302 redirect can make SEO tricky, since you'd have to get into how search engines behave with these redirects. For example most search engines will not use the original URL as a source for keywords when you use a 301 redirect.
In addition to 301 and 302 redirects, some DNS providers (like DNS Made Easy) also provide what they call a "masked hidden-iframe redirect". The page will render inside a hidden iframe, so the URL does not change in the user's browsers. However this makes SEO even more tricky, and it will not allow users to bookmark internal pages, or to reference them easily.
As you can see, this option is less than ideal, but it is one option to consider in some situations. Also note that at the moment, HTTP Redirection using 301 redirects is the suggested workaround for the Naked Domain Issue 777 on the AppEngine issue tracker.
Reverse Proxy
Another option could be to set up a small server somewhere else, like a small Amazon EC2 Instance, and set up a simple reverse proxy. You would be able to set this up very easily, just by using Apache and mod_proxy (or various other alternatives). This would allow you to ask your clients to set up a normal A Record pointing to this instance, while the Apache HTTP server would be acting as a proxy to your AppEngine.
The fundamental configuration directive to set up a reverse proxy in mod_proxy is the ProxyPass. You would typically set it up with one line like these for each VirtualHost (for each client domain):
ProxyPass / http://www.enmystore.com/mystore/
The configuration of the remote proxy could be easily handled by your back-end software.
This is a neater solution which gives you plenty of control - but there are obviously some costs for these benefits. First of all, there is the expense to host the reverse proxy. You would also be adding another point of failure, so you have to add this to your high-availability plan. In addition, if you are serving some pages through SSL it can become quite complicated.
Another option is to have each customer sign up for google apps, and then add your appengine app to their app. That way they can manage the url. They will need to use a cname for this, so urls will be limited to something like 'store.customer.com' You will have to support the multitenancy off of the host-header, but that isn't hard to do given that you already have a way to support multitenancy already. You might want to do the setup for the first couple of clients yourself so you can document the easiest way to set it up.
The rietveld code review app does this as you can add it to your google apps domain. See http://code.google.com/p/rietveld/wiki/CodeReviewHelp#Using_Code_Reviews_with_Google_Apps for more detail.
The preferred option is probably to offer your solution through the Google Solutions Marketplace: http://www.google.com/enterprise/enterprise_marketplace/about.html
We did something similar to Daniel Vassallo second proposal.
We created a python app on the Heroku cloud
(there is no limit for connecting custom domains).
This app is using python requests 1.2.0 lib to get the correct page from your app engine application according to the request domain.
all you need to tell your clients is to put your Heroku app url as their CNAME
For naked domains you can always use wwwizer

Resources