Problem hosting a single-page application with Amazon S3 and CloudFront: how to differentiate 403 from S3 vs 403 from the backend service? - amazon-cloudfront

I have a single-page app that is developed in one of the modern JS frameworks.
This single-page app only has a single entry point (index.html).
It handles routing and other page logic through JS, which means that when a user goes directly to, or refreshes the page on, a non-root URL we want them to pull down the index.html file instead of a file stored at the URL path location (like in a statically hosted website).
If a resource behind the URL is not found, S3 returns 403. Therefore, in CloudFront, we have configured the following rule:
Now, I am working on the Authorization layer in the backend that legitimately is returning 403 if the subject doesn't have enough rights to access the API.
And, instead of returning 403, CF, for obvious reasons, is returning 200 with the index page.
Is there a way to fine-tune this behavior? Thoughts?

I was able to solve this by using the following approach:
turn on Static Web Hosting on S3
replace the S3 bucket name in CloudFront origin with the S3 Static Website URL.
remove Error Pages from CloudFront.
The error pages will be handled by the respective origins instead of CloudFront.

Related

how can I stop people from downloading my Assets

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

Azure CDN preventing Storage Account Static Site Authentication with Active Directory

I currently have an Azure Blob Storage Account setup with Azure CDN to host a Static Site. This Static Site is connected to an App Service backend and uses frontend-based authentication using Active Directory baked into the application code with MSAL.
When it was initially deployed and running off of the Static Site's URL alone, I was able to authenticate without fail. The auth popup would present itself, I would provide credentials, and the Active Directory sent back a token that I then confirmed with the backend and successfully redirected to the post-auth landing page.
The Problem I'm having now is that when I proceed to the URL provided by the Azure CDN (rather than the Storage Site's URL), the popup for authentication opens and allows me to provide credentials, but instead of closing and redirecting upon token reception, the popup simply hangs there. It's also interesting to note that the popup's URL is listed as the Static Site URL and not the CDN URL. The token comes back and is present in later portions of the URL, so it must be a mis-match between the URLs that's causing the issue.
I've Tried changing out the Static Site's configured Reply URLs to match the CDN, and it didn't make a difference. I've also added the CDN URLs (both the custom one and the endpoint .azureedge.net one) to the Active Directory list of Reply URLs.
The CDN is providing a certificate for the custom URLs to use, so we need that in order for the custom URLs to work properly. To be clear as well, the authentication works when using the Static Site URL, but not the CDN URL.
Has anyone else run into an issue of this nature? If so, have you solved it?
For anyone who may come across this, the solution was much more simple than I had anticipated. The MSAL configs for the frontend needed to be using the new CDN URL (which I figured), but the CDN itself needed to be purged and the changes picked up from the Blob storage.

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.

node.js as front end authentication for cloudfront + s3

I'm a fan of using cloudfront + s3 to serve static sites. I have a use case where I need to run a site in s3, but I need authentication. I'd like to be able to handle this in a serverless way, but I need some sort of application to handle the auth logic.
My idea is that I could run a node.js application on something like elastic beanstalk in front of cloudfront to handle authentication.
Basically a user makes a request to the application, my app authenticates the user with our authentication backend, creates a cookie returns it and then serves the private cloudfront url for the requested resource. Am I on the right track here?
The idea is to have a gated s3 website that a user can browser after authenticating. I think this could be achieved using node http and passport to authenticate and then use the aws sdk to create the signed cookie.
Yes. This makes sense.
Depending on your use case, it might be sufficient to use AWS API Gateway + Lambda for login page and authentication (instead of elastic beanstalk).
Also AWS recently announced Lambda#Edge which is a way to execute Lambda functions in response to Cloudfront events. That could work for what you are describing - http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/http-response-generation.html

How to use Cloudfront to protect my files

I have a bunch of images on my S3 which is linked with Cloudfront.
Now I have a web server and I only want users to view the image through my website so I can't just give out links to the image. How do I set that?
It appears that your requirement is:
Content stored in Amazon S3
Content served via Amazon CloudFront
Content should be private, but have a way to let specific people view it
This can be accomplished by using Pre-Signed URLs. These are special URLs that only work for a limited period of time.
When your application determines that the user is entitled to view an image, it can generate a Pre-Signed URL that grants access for a limited period of time. Simply use this URL in an <IMG> tag as you would normally.
See:
Amazon S3 pre-signed URLs
Amazon CloudFront pre-signed URLs
Since your content in Amazon S3 will be private (so users cannot bypass CloudFront and access it directly), you will also need to grant CloudFront permission to access the content from S3. See: Using an Origin Access Identity to Restrict Access to Your Amazon S3 Content
Another option, instead of creating a pre-signed URL each time, is to use Signed Cookies. However, this doesn't give fine-grained control for access to individual objects -- it's more for granting access to multiple objects, such as a subscription area.

Resources