how can I stop people from downloading my Assets - node.js

I have a bunch of 3D models on my web app and they are accessible to public to see but I don't want anyone to download them. I use Amazon S3. Is there any way to achieve this?

In the default web app - as already commented - if the client can "see" the resource, it is already on the client's side.
There are two aspects of the question. You want to prevent accessing the models from the public (unauthenticated) client or even the authenticated.
To prevent unauthorised access to S3 resources used for web apps, the common option is using the pre-signed S3 url. The application generates temporary resource link only for authorized users.
If you want to prevent access to resources even authorized users, to you can render the view on the server side e.g. see AWS AppStream

Related

How to allow a public app to connect to the GitHub API v4 without an access token?

I have decided to try to manage releases of one of my apps on GitHub as with GitHub Actions, I can build on Mac, Linux and Windows and automatically push the artifacts to the GitHub Releases page, where anyone can go and download the app from.
However, I want my app to self-update, so the app itself also needs to be able to query what's the latest version in the repo releases, and then download the relevant asset for the user's OS... which I thought would be a non-issue... however, there's no way to access the GitHub API v4 without either an OAuth app or a personal access token.
I don't want an OAuth app because the users of my app are absolutely not expected to be GitHub customers. So I tried to use a personal access token whose only scope was access to public release assets (which, again, is a public resource anyone can go and manually download).
As this token can't do anything you or anyone else can't do manually, even without a GitHub account, I thought it would be fine to put the token in the source code of my application, but GitHub revokes the token when it detects it on a commit.
Is there a good way to work around this? Should I put the token in a GitHub secret and then try to replace a placeholder with it during compilation?? I wanted to avoid that as that makes it hard for me to test the app locally, and also, it doesn't solve anything as anyone can easily decompile the app and find the token there (supposing GitHub would not detect the secret is present in the "processed" sources during compilation).
Any suggestions would be appreciated.
however, there's no way to access the GitHub API v4 without either an OAuth app or a personal access token.
The GitHub API v3 does support unauthenticated calls, but it's limited to 60 requests/hr per IP address: https://developer.github.com/v3/#rate-limiting
For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Unauthenticated requests are associated with the originating IP address, and not the user making requests.
The Latest Release API docs will show you what information is returned, but I suspect you'll need to make a secondary call to List Assets for a release to know the files the client needs to download.
If that's not satisfactory (e.g. you know you'll have many clients try to update using the same IP address), and you'd like to ensure they aren't being rate-limited, read on for a different approach.
Is there a good way to work around this?
How I would tackle this is by deploying a small web service (e.g. Heroku dyno) that your app can will call without needing authentication, which then performs the actual lookup for the latest version (using a PAT that gets embedded as an environment variable) and returns a simple JSON response that the client will understand.
Benefits:
no token embedded in client
development mode can even call same service
add logic to service that the client would perform to simplify your app
e.g. call /latest/beta or /latest/stable to indicate it's looking for a specific channel
perform both API calls and return the assets that the client needs
can update token in service whenever necessary (e.g. to refresh token) without changing client
can cache response to reduce risk of being rate-limited
Downsides:
more moving parts to manage in your overall architecture
need to worry about uptime of the service if there are lots of clients connecting
this can be offset by making the client resilient to failure cases

How to host a static s3 website with cloudfront that uses cognito built in login pages

I am beginner to aws. I want to host a static S3 website with cloudfront distribution but I want to add the cognito built in login page first when user hit the website url.I am not sure how to do that. I am seeing multiple solutions for S3 + cloudfront or cognito but I am not getting any solution as to how to integrate S3 website + cloudfront + cognito bult in page.
Can someone please suggest how to do that?
Thanks in advance!
I would recommend looking into AWS Amplify (https://aws-amplify.github.io/) which is very much like AWS's answer to Firebase. It allows you to very quickly spin up AWS resources such as Cognito, Storage (including for websites) with S3, apis, databases and much more.
AWS Amplify has a ready-made and configurable Authenticator component for both React and Angular projects that integrates with Cognito and will immediately handle sign ups, log ins, password reset etc.
For Angular (https://aws-amplify.github.io/docs/js/angular) see the Authenticator component.
For React (https://aws-amplify.github.io/docs/js/react) see Add Auth.
I hope that helps.
CloudFront doesn't have native Cognito integration, at least as of this writing.
CloudFront does, however, have a feature called Lambda#Edge that allows you to provide server-side JavaScript that CloudFront can execute at specific trigger points during HTTP request (and response) processing, allowing the code to examine aspects of requests (and responses) and then tell CloudFront to modify how things are processed, such as allowing or denying requests based on certain criteria (such as for authentication purposes).
The AWS Blog post How to Use Lambda#Edge and JSON Web Tokens to Enhance Web Application Security appears to describe in detail how you can use Lambda#Edge to roll your own Cognito-based solution, and includes a CloudFormation stack template that will actually launch this solution in your own AWS account, where you can then examine the code and configuration, to see how it all works.
With this setup, CloudFront can use a standard Origin Access Identity to authenticate itself when making requests to the S3 bucket, so S3 doesn't need any special configuration -- S3 will be unaware of the Cognito authentication occurring on the front-end.

GCP - Compute Engine to Storage per group/user access ACL with custom Auth system

I've built a simple messaging application with NodeJS on GCP that, at the moment consists of a single compute engine instance. I'm using this to learn the stack and how GCP sits together.
My application has it's own user/password registration system and allows users to message each other in 'groups'. These groups can consist of 1...n users and one user is responsible for adding/removing users from a group. They can do this at any time.
I want to allow the users to upload pics and ideally I will then store them in Google Storage. But I want to make sure that only users in a room where an image is uploaded can view that file.I know that GCP makes use of IAM roles etc. but with the authentication being in my system am I expected to update IAM policies every time via the API? In a scaled solution would this work?
My initial thought is that I should do the authentication at an app level. e.g my Compute Engine instance can talk to Storage so when a user requests to a view an image by its url - such as example.com/uploads/:id
I then validate that the current user can view the upload with id :id and if they can, then serve the image from the app. Would this work? Would it be compatible with utilising Google CDN? Is there a preferred solution for doing something like this bearing in mind I'm not using firebase (which I understand can use access tokens for auth) but I'm using my own authentication based on username/password combos with sessions?
For examples of sharing and collaboration scenarios that involve setting bucket and object ACLs, you may take a look at Sharing and Collaboration. As you mentioned and also noted here, you can create a service that authenticates users and redirects them to a URL signed by a service account and this solution helps the scaling amount of users as well.
You must give Cloud CDN permission to read the objects by adding the Cloud CDN service account to Cloud Storage's ACLs for restricting the users on reading the objects.
I should also add that Cloud Storage is integrated with Firebase and you may acquire Firebase Security Rules for Cloud Storage to authenticate and authorize the users.
So it looks like I actually have 2 options here.
I can use signed urls https://cloud.google.com/storage/docs/access-control/signed-urls#signed-urls and grant temporary access to the files to the users in question. I would just need to regenerate this whenever required.
My second option (event though I said I don't want to migrate) is to use Firebase Auth. I wasn't aware it actually supported email/password migration and validation and is actually free regardless of number of users. The only thing I'm not sure on here is how Storage is configured with relation to my current GCP project.

How to restrict Firebase data modification?

Firebase provides database back-end so that developers can focus on the client side code.
So if someone takes my firebase uri (for example, https://firebaseinstance.firebaseio.com) then develop on it locally.
Then, would they be able to create another app off my Firebase instance, signup and authenticate themselves to read all data of my Firebase app?
#Frank van Puffelen,
You mentioned the phishing attack. There actually is a way to secure for that.
If you login to your googleAPIs API Manager console, you have an option to lock down which HTTP referrer your app will accept request from.
visit https://console.developers.google.com/apis
Go to your firebase project
Go to credentials
Under API keys, select the Browser key associated with your firebase project (should have the same key as the API key you use to initialize your firebase app.)
Under "Accept requests from these HTTP referrers (web sites), simply add the URL of your app.
This should only allow the whitelisted domain to use your app.
This is also described here in the firebase launch-checklist here: https://firebase.google.com/support/guides/launch-checklist
Perhaps the firebase documentation could make this more visible or automatically lock down the domain by default and require users to allow access?
The fact that someone knows your URL is not a security risk.
For example: I have no problem telling you that my bank hosts its web site at bankofamerica.com and it speaks the HTTP protocol there. Unless you also know the credentials I use to access that site, knowing the URL doesn't do you any good.
To secure your data, your database should be protected with:
validation rules that ensure all data adheres to a structure that you want
authorization rules to ensure that each bit of data can only be read and modified by the authorized users
This is all covered in the Firebase documentation on Security & Rules, which I highly recommend.
With these security rules in place, the only way somebody else's app can access the data in your database is if they copy the functionality of your application, have the users sign in to their app instead of yours and sign in/read from/write to your database; essentially a phishing attack. In that case there is no security problem in the database, although it's probably time to get some authorities involved.
Update May 2021: Thanks to the new feature called Firebase App Check, it is now actually possible to limit access to your Realtime Database to only those coming from iOS, Android and Web apps that are registered in your Firebase project.
You'll typically want to combine this with the user authentication based security described above, so that you have another shield against abusive users that do use your app.
By combining App Check with security rules you have both broad protection against abuse, and fine gained control over what data each user can access.
Regarding the Auth white-listing for mobile apps, where the domain name is not applicable, Firebase has
SHA1 fingerprint for Android apps and
App Store ID and Bundle ID and Team ID (if necessary) for your iOS apps
which you will have to configure in the Firebase console.
With this protection, since validation is not just if someone has a valid API key, Auth domain, etc, but also, is it coming from our authorized apps and domain name/HTTP referrer in case of Web.
That said, we don't have to worry if these API keys and other connection params are exposed to others.
For more info, https://firebase.google.com/support/guides/launch-checklist

Securely store data on a web server

I'm planning on making an android application that sends user data to a web server and stores it temporarily in a database. Now I've never worked with databases or web servers before, but after reading a bunch of tutorials and a few days of hacking away I managed to get a node.js server with mongodb up and running on the openshift platform.
Right now anyone can interact with the database just by sending a GET request or even just pulling up the url in a browser. Is there a way to prevent that by happening or would I have to maybe encrypt the data myself before storing it?
You describe a typical web application using REST APIs. To secure it, do two things:
Deploy your REST APIs (or the entire site) using HTTPS instead of HTTP. This provides end to end encryption so your sensitive data cannot be viewed while in transit
Add an authentication and authorization mechanism, so that only authenticated endpoints can access your REST APIs.

Resources