How do I customize/limit content for multiple customers on a static S3 site?

0

How do I customize/limit what a web user (customer - not administrator!) sees on my static S3 site? I have searched high and low for which approach to take. I've successfully limited access with CloudFront & Lambda but that approach only allows one user/password for all restricted content. I would like my customers to log on individually (lowest level) and have content filtered for each customer. I do not want my customers to see other customers or other customer's content. I have tried following "Signed cookie-based authentication with Amazon CloudFront and AWS Lambda@Edge: Part 1 & 2" but boy did that leave a gaping hole between the two documents (i.e. where do you point the login form???)! I think I am looking for: Individual customer sign on / password (cognito?) Filtering/limiting content (by prefix?) determined by cookie or token or ??? Please just point me in a direction?

3 Answers
0
Accepted Answer

Hi sschlegelmilch - Thank you for adding additional details!

Here is how I would set this up.

  1. Implement Cognito on the static app. Full disclosure, I have never done this, but the goal is to get a JWT generated when a user logs in. Per the Cognito documentation that I linked above, it looks like the JWT is generated by default on a successful login so I hope that this step is not too difficult.
  2. When the user successfully logs in, set the JWT generated above as a cookie.
  3. In CloudFront, create a new cache behavior for /pricing (I am making this up, but some path that should be protected). In this behavior you will want to use this CloudFront function to handle checking the JWT and verifying if the request should be allowed/denied. This Lambda might require a few small modifications to check the JWT token in a cookie value, as I think it checks for a JWT in a query string by defaul, but it isn't too difficult. If you get stuck let me know.
  4. Change the default error behavior in the CloudFront function above to issue a redirect back to the Cognito login page.

So now a user will access your site, and can browse around just fine. When they go to the Cognito login and successfully login they will get a JWT cookie. When they go to the protected path (/pricing) they will hit the Lambda that checks their JWT token. If the cookie exists and the JWT token is valid then the request is allowed through and the user can see the protected content. If the JWT token is missing, or is invalid then the user will be redirected back to the Cognito login page.

Again, I haven't set this up myself personally, but I believe this should work.

profile pictureAWS
answered 2 years ago
0

Hi @sschlegelmilch,

Without knowing the specifics, I will make some assumptions. Please feel free to reply and add additional details if you think it will help.

I am going to assume that your static site that is running on S3...

  1. Does not have user authentication built-in, and you are trying to find a way to add it.
  2. Has a specific URI that is unique to each user, and you want to make sure user A gets their unique content, user B gets their content, etc. For example, a page named /myaccount

Starting with #1, you can add authentication to your site using AWS Cognito. Take a look at the integration code snippets half-way down the Cognito page found here. For a deeper dive, check out the Cognito documentation here. Once a user is logged in, you can route that user within your web application accordingly.

At this point, I am assuming you have authentication setup correctly, and you are able to route individual users within your web application. However, if you add in any caching (like CloudFront for instance) then you risk serving cached content to the wrong user. For example, user A hits /myaccount and the page is cached. User B attempts to access /myaccount and they get user A's cached version of the page. To resolve this, you need to make sure that you are creating a unique cache key for each version of the page (user A's page, user B's page, unauthenticated users, etc). To accomplish this you need to know how your application identifies authenticated users. In the case of Cognito, this is done using a JWT passed in the query string. So using that example, you would go into your CloudFront cache policy, and add the appropriate query parameter to the cache policy. This will now include the specified query parameter in the cache key, so each user will have their own unique copy in cache.

Please let me know if any of my assumptions are incorrect, or if you have additional questions.

profile pictureAWS
answered 2 years ago
  • Jeremy, I also thank you for taking time to address my question. I really didn't expect someone from AWS to answer, but that is impressive! Your assumptions... Yes, I am running a static website on S3. I have blocked all public access to the S3 bucket and have been using CloudFront & Lambda to access both public (index, login, css, js files...) and restricted content. However, I have tried two methods to PERSONALIZE content... The first lambda I tried worked fine by requiring web users to enter a username/password to go past the login/index pages. Again, it worked well except for the fact that once a user had authenticated they had access to ALL restricted content. I wanted to go one level deeper... So I followed (several attempts) at using cognito to perhaps set a cookie that I could read later on a login page. I tried to follow the AWS tutorial entitled "Signed cookie-based authentication with Amazon CloudFront and AWS Lambda@Edge: Part 1 & 2".
    Sidenote... Many times I have encountered several of the "how-to" documents on AWS to be outdated (i.e. referencing menu items that have changed, etc.), but that is another discussion. I got stuck between Part 1 & 2. (to be continued...)

  • I was thinking I could use javascript to set the login button to point to the individual customer page. I was HOPING that a cookie could be set so that individual customers could only see files with their username (or account #) in the prefix ('folder') of their customized content and would restrict them from seeing other's content (and identity/# of other customers). Your caution of CF serving up cached content is interesting and I will study that. Also, whether to use tokens or cookies does not matter to me as long as it works. *I will take your advice and study using Cognito to set JWTs for unique identifiers. Question... I would like to verify (with you) that setting a JWT will allow me to restrict web users to certain prefixes of content? Let me give you an example... As I said before, I am trying to give public access to 'assets' (css, js, etc.) and product info but I want to individualize pricing information. Does that make sense? Again, I appreciate your help! Really!! P.S. It would be great to have someone from AWS critically step through the two part document I referenced above. That MAY have been a solution for me but I believe there is a gap between the two parts. Part 1 illustrates using a form to authenticate but does not indicate what "get action" the form should point to.

0

Hi, @sschlegelmilch

You can authenticate by delivering a front-end website from CloudFront and accessing the back-end Lambda from JavaScript.

However, in general, it is necessary to communicate from JavaScript to the backend via HTTP / HTTPS, so use Lambda Function URL / API Gateway + Lambda to enable communication from the frontend JavaScript to the server-side API server. recommend.

Besides Lambd, you can also use containers and EC2. In either case, JavaScript delivered from CloudFront communicates via HTTP / HTTPS.

profile picture
EXPERT
iwasa
answered 2 years ago
  • iwasa, Thank you for taking the time to address my question. I appreciate that. That said, your answer to me is confusing. Yes, I do understand and currently use CloudFront to connect to my S3 bucket. I have also tried two different methods of using Lamda to add authentication through Cloudfront and the first method worked just fine. What I don't follow is your reference to HTTP / HTTPS. That has me scratching my head. Yes, of course I am using HTTP (redirect to HTTPS) / HTTPS but I have no idea what that has to do with anything. Sorry for MY confusion.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions