A serverless video hosting app with gated user authentication.
Inside Story uses Gatsby to display the video pages and a bunch of AWS resources, described with CloudFormation, to host, provide SSL, and handle authentication.
This project started out as an attempt to replace a simpler video hosting setup with something "serverless". It ended up being a big experiment with AWS and an opportunity to learn. (Read: this is way more complicated than the volume of my video site requires :) ) I wanted to have some public facing content - the login page, headers on the individual video pages so that previews would appear in social media postings - but also restrict access to videos of my kids. I wanted the restrictions to be real - ie not just hiding stuff with javascript. Finally, I wanted the setup to be self documenting so that there are no obscure settings deep in the AWS console to forget about.
The CloudFormation template has all the details in its 30-odd resources, but keep reading for an overview.
Allows for every user to be specifically granted access by the administrator. This is a video hosting site for family videos. I do not want it to be public, nor do I want users to have to remember separate credentials. I want to announce new content on social media and allow those users who have been authorized to immediately have access to that content.
- GET site page. User sees page with "login with Facebook" button.
-
Login with Facebook. This redirects the user to a Cognito URL, which again redirects to Facebook login.
-
After logging in with Facebook, the user agent is redirected back to Cognito. Cognito executes a PreAuth hook, which is a Lambda function that checks for the presence of the user in a DynamoDB table.
3a. If the user has not yet been authorized in the DynamoDB table, they are redirected back to the site with a message explaining that their request will be reviewed. The Lambda function also adds the user to the DynamoDB table, leaving them unauthorized, and uses SES to email the administrator (me!). User flow ends here for these users.
3b. If the user has been authorized in the DynamoDB table, they are redirected back to the site with Cognito tokens as query string params.
-
An AJAX request is made to an API Gateway Endpoint. The Cognito accessToken is sent as the Authorization header. The API Gateway Endpoint validates the accessToken with Cognito before permitting the request.
-
If the token is valid, the Lambda function integrated with the Endoint provides signed cookies and the Endpoint returns them in its response. Because the API Gateway is on the same domain as the protected assets, these cookies will be used when requesting the protected assets from their CloudFront Distribution.
-
Protected assets (videos) are requested from a CloudFront Distribution. This Distribution is configured to required signed cookies. The user can view protected content.
To start a new feature:
- create a new branch (no underscores)
- make changes to cloudformation.yml
npm run stack:create
npm run stack:status
to check status or https://console.aws.amazon.com/cloudformation/homenpm run develop