Build Your Own Netflix-Like Streaming Platform — “Futureflix”
You don’t necessarily see yourself as a hapi expert. But know you that learning the insights of this framework is helping you grow.
You’ll get to know the details of hapi and parts of its plugin ecosystem by working on a larger project.
In learn hapi, you’ll implement a complete platform from start to end.
Get a grasp on Futureflix and what this project is about. Also, you’ll see the topics and concepts covered within this learning path.
This is all about preparing your project and stack. Get to know the stack of choice. Then it’s enough theory, you’re jumping right into the project’s structure and install the first NPM dependencies. When finishing all tasks in this tutorial, you’ll already have a minimal Futureflix running on your system 📺
Don’t store sensitive data within your project’s code base! We’re talking about API keys, database credentials, OAuth client IDs and secrets, etc. You know the importantance to keep secrets outside your repository.
MongoDB is the data store for Futureflix. Bootstrap a database instance using an Ubuntu Vagrant box. Define the environment variables to connect from your hapi project using Mongoose.
request.userwithin route handlers.
A common error scenario is an unavailable page on your platform. Use this missing piece as a chance to help the user to keep context and a route back to safe lands.
What if you could access the requesting user data via
request.user? That would remove some extra lines of code within multiple route handlers and still keep the code readability. Also, it’s a short statement and you can immediately recognize what user data is accessed.
We’ve developed hapi-dev-errors to skip the the command line lookup for 500 errors. You’ll increase your productivity by using an elegant and expressive error view in the browser.
A sign up flow with email address and password is one of the de-facto features web apps implement. Assumingly, every web developer has implemented this part of a boilerplate themselves. You know what? That’s totally fine, because it’s important to know the fundamentals of all this and that there’s more involved than a web view with a form.
Add the second part that belongs to user onboarding: the login flow. The current setup of your Futureflix instance allows users to sign up. You’ll add the missing login by following this tutorial. On top of that, you’ll remember the user with a cookie-based session.
At work, you may need to change your password every 45 or 90 days. I guess you’ve a password with an increment at the beginning or end 😉 Not that I’d do that 😏 Following this tutorial, you’ll implement a complete password reset flow with an email notification including password reset instructions for the user.
You’ll make use of Gravatar and grab the user’s profile picture. This personal touch helps the user to identify with your Futureflix platform. It also shows your effort to fetch the picture, even though you might fall back to a default one.
Let users choose their unique username in your Futureflix app. With additional fields, like their Twitter handle or personal homepage, individual users can highlight themselves on your platform.
Auto-generate a username based on the user’s email address when saving a new user in MongoDB. Because usernames should be unique throughout your platform, you’ll take care of duplicates and generate a funky alternative 😉
Add a watchlist to Futureflix to save movies and shows for later. It’s easier to decide on a Friday night movie from less choices 😁
Protect your app against cross-site request forgery, in short CSRF. It’s an attack against your website where another website sends unauthorized commands from a user’s account.
Fun fact: CSRF is called sea-surf.
With growing data sets in your Futureflix app, you don’t want to deliver all documents at once. This puts a ton of load onto your database, your application and the user’s browser to display everything. Implement pagination for the movies overview page to show a maximum of eight items at once.
This is the starting point to extend your existing Futureflix app with a REST API serving JSON endpoints 🚀
While creating the Futureflix API, you noticed that JSON responses contain the
_id and version key
_id field feels wrong due to the underscore prefix, so let’s remove it and keep only the
id field. The version key
__v isn’t necessary in the response at all and you want to remove it from the JSON as well.
Returning ALL data for requests isn’t a good practice. With a growing set of TV shows, your API response will grow respectively. Instead, let users fetch data when needed and reduce the amount of outgoing JSON data with pagination
Let users customize the result of API endpoints with query parameters. Implement the functionality to extend JSON responses for TV shows gradually with seasons or seasons and episodes.
hapi generalizes error messages for failed validations and only tells you the source of the issue, like “Invalid request
query input”. This isn’t helpful for requests containing multiple query parameter values. Make it approachable for developers to find the issue with detailed error messages.
Validating incoming user data is an important piece of your API. On your end, provide helpful error messages for faulty validations. Let developers find their problems with your API by pointing them directly to the issue and a helpful resource to find more details, like the API documentation.
Your Futureflix API grows in functionality and only you know how to use it. It’s important to document endpoints as early as possible so that external developers get a grasp on using it.
Your initial API documentation for Futureflix uses hapi-swagger to generate an endpoint overview from your project configuration. By default, hapi-swagger registers the
/documentation route. If you want another path, like
/docs, you can customize it. You’ll do that in a minute 😉
Your Swagger API documentation becomes a beneficial place for developers. The integrated Swagger UI allows anyone to send sample requests against your endpoints. It’s a good way to see the actual response format and data of endpoints.
In this tutorial, you’ll configure Swagger to support API key authentication. This allows users to authenticate requests with their personal JWT in the Swagger UI.
Imagine the flow to check the response for an endpoint that requires authentication. You need a JWT which requires you to log in first. Then copy and paste over the token value for the actual request. It ends up sending subsequent requests including authentication for that quick test. There’s a much better way using Postman, an API development and testing tool.
For web applications, you’re most likely in charge of the web views and can adjust view data changes to the layout files. This doesn’t apply to APIs, because you’re not in control of every consuming client. Fortunately, there’s a common approach to evolve your APIs: versioning. This tutorial walks you through API versioning with request headers and shows you the implementation details.
With the username and password login, you’ll create a user-specific JSON web token (JWT). You’ll use this JWT in the second tutorial on API authentication where you’ll proceed with the authentication handling and switching endpoints from public to private.
In this tutorial you’ll make the switch for all endpoints from publicly available to require JSON web token (JWT) authentication to access the endpoints.
Authenticating users with JSON web tokens is a convenient strategy. In this tutorial, you’ll implement a token refresh handling in your application that returns a JWT which is valid for 15 minutes in exchange for a refresh token.
The implementation from the previous tutorial works well for a single login because you allow a single refresh token. As soon as your users log in from different devices, the latest login has the valid refresh token. this tutorial is updating the existing implementation to support refresh token handling for JWT authentication on multiple devices.
In this tutorial, you’ll improve the implementation by using hapi’s framework capabilities along the request lifecycle. You’ll move the first two tasks into an authentication strategy to focus the responsibility of the route handler to create a new refresh token and send it along in the response.
Security must be a major concern in every application. You should assign rigid security rules for your authentication-related API endpoints. In this tutorial, you’ll rate limit the refresh token route to protect the endpoint from brute-force attacks.
You can guess that passing all concerns to an authentication token that lives on the client is not an appropriate approach to build secure application. This tutorial looks at four different ways to revoke JWTs and also explores why revoking tokens is a must have, not a nice to have.
A thing to keep in mind with JWT is the token lifetime. Every JWT has its own expiration time. You can’t simply revoke a JWT to invalidate the token. This tutorial walks you through JWT blacklisting with the help of Redis.
Because there’s no straightforward way to logout users with JWT, we’ll look at two different approaches. This first one is a “soft logout” invalidating only the long-living refresh token and not the short-living JWT itself.
In contrast to the first tutorial, you’ll now implement a JWT logout that invalidates both tokens, the JWT itself and the refresh token, immediately. A user must re-login to interact with API endpoints that require authentication.
The previous tutorials on basic JWT logout and immediate JWT logout focused on the functionality to invalidate tokens. They didn’t focus on project architecture, clean code, or where to apply actions. That’s what you’ll change in this tutorial: refactor your code to find a better place to revoke the JWT and refresh token.
Security is a high-priority concern in every application. You should always look out for vulnerabilities in used libraries and your infrastructure. The same holds true for JWT because the token signing contains a hashing or encryption part. In this tutorial, you’ll learn how to switch the JWT signing algorithm, like switching from HS256 to HS512 or HS384 to RS256.
In this tutorial, you’ll replace the used third-party libraryto authenticate requests with your own hapi authenticationscheme. Your auth scheme will match the needed functionalitybecause it’s dedicated to your platform and fits the use case.
Claims represent the data you’re storing inside the JWT. AJWT claim set is the JWT payload consisting of more than onekey-value-pair. In this tutorial, you’ll walk through thedetails of JWT claims. You’ll look at registered claims andthe differences between public and private claims.
JWT also supports symmetric and asymmetric signing algorithms. Asymmetric algorithms, like
RS256 use a key pair. This key pair consists of a private and public key. The private key is used to sign a new JWT and the public key is used to verify the signature This tutorial shows you how to use JWTs with asymmetric algorithms —like
RS256— and authenticate users.
Created tokens didn’t use any payload encryption. In case an attacker has access to a user’s JWT, they can seamlessly read the token payload. This tutorial walks you through a simple way of encrypting your custom claims before creating a JWT.
A Node.js mailer sending emails to welcome a new user on your platform is nice onboarding experience. A more critical part is a mail to reset a user’s password. This is what you’ll add to your Futureflix app. With an existing sign up functionality, you’ll use the opportunity to send a welcoming email for your platform.
It’s an advanced path and requires basic knowledge about hapi. If you’re familiar with the concepts of plugins in hapi, routing, view handling & template rendering, you’re ready to rock 🤘
No expiration date. No plans to retire it. At some point, we might update or extend it though!