I’m new to AWS and just exploring possible architectures using the tools like AWS cognito, AWS Cloudfront, and/or AWS API Gateway.
Currently, my app is deployed in an EC2 instance and here is the outline:
Frontend: React app running on port 80. When a user goes to https://myapp.com, the request is be directed to my-ec2-instance:80.
Backend: Nodejs + Express running on port 3000. After the user loads the frontend in the browser, when he interacts with the website, http requests are sent to https://myapp.com/api/*, which are routed to my-ec2-instance:3000;
I use nginx/openresty as a single entry point to my webapp, and it does authorization with AWS Cognito, and then reverse-proxy the requests based on path:
Now, instead of managing an EC2 instance with the nginx/openresty service in it, I want to go serverless.
I plan to point my domain myapp.com
to AWS CloudFront, and then Cloudfront acts as the single entry point to replace the functionalities of Nginx/Openresty. It should do the following:
-
Authorization with AWS Cognito:
When a user first visitsmyapp.com
, he is directed to AWS Cognito from AWS Cloudfront to complete the sign-in step. -
path-based reverse proxy: I know this can be done. I can configure this from the CloudFront configuration page.
But for 1, Can Cloudfront do authorization with AWS Cognito? Is this the right way of using AWS Cloudfront?
After reading the AWS doc and trying with Cloudfront configurations, I started to think that Cloudfront is not build for such a use case at all.
Any suggestions?
3
Answers
Few ideas.
Frontend:
Use S3 + CloudFront distribution.
About the authentication, you can try using a Lambda function "linked" to the CloudFront distribution, redirecting to Cognito.
Backend:
Deploy on Fargate, EC2 or do you prefer.
Put an Application Load Balancer (ALB) in front of the endpoint, so you can define rules with redirects, forward, deny, etc.
You mentioned "serverless", but using ec2 which is a server. You can use AWS lambda (Node JS) for backend and S3 for front-end. AWS API gateway has built in authorization feature where you can use AWS Cognito. Cloudfront is for content delivery cached in edge locations to deliver content faster from nearest edge locations where the user is located.
You can follow the below steps to implement serverless concept in AWS.
Create the front end and upload to S3
Configure AWS Cognito and grab the following
UserPoolId: ‘xxxx’,
ClientId: ‘xxxx’,
IdentityPoolId: ‘xxxx’,
Region: ‘xxxx’
Use aws-cognito-sdk.min.js to authenticate user and get the JWT token, sample code can be found here. This JWT token needs to be passed to each and every API call in the header section. If using AJAX then sample code is
var xhr = new XMLHttpRequest();
xhr.setRequestHeader("Authorization", idToken);
Configure AWS API gateway and cloudfront – follow documentation
In API Gateway configuration select Cognito for those API’s for which you want to use authorized access.
Create AWS Lambda functions for the backend and link to API Gateway.
PROBLEMS
It feels like your current problems are:
SOLUTION APPROACH
If you can separate web and API concerns you can solve your problem:
TOKEN HANDLER PATTERN
At Curity we have put together some related resources, illustrated in the following picture:
It is a tricky flow from a deployment viewpoint, though the idea is to just plug in the token handler components, so that your SPA and APIs require only simple code, while also using the best security.
AWS CODE EXAMPLE
Out of interest a React sample of mine uses this pattern with Cognito, and is deployed to Cloudfront.