How Twilio Keeps Internal Docs Secure with Okta and Netlify

February 08, 2022
Written by
Reviewed by

Secure Internal Docs Netlify Okta

Twilio is releasing netlify-okta-auth as an open-source package to help everyone solve the same problem we had, keeping private and securing an internal docs Jamstack site.

Building an internal docs site at Twilio

At Twilio, we wanted to create a new site for documenting our internal products. The philosophy was that we should provide just as great of a developer experience for our internal engineers as we do for our developer customers.

A company the size of Twilio has many internal tools, services, and processes for building, deploying, and maintaining our public APIs. There are thousands of engineers that need to use these internal products, and we needed a comprehensive and high-quality documentation site for them.

Finding Docusaurus, a Jamstack documentation framework

So, we embarked on the search for the right documentation platform. We finally settled on Docusaurus - an open source, Markdown-powered documentation platform. Oh yeah, and it is built around Jamstack. Docusaurus uses React to build your site, but when you’re ready to publish, it creates a static version of every page on your site that you can deploy to a hosting provider like Netlify. This approach is similar to popular general-purpose frameworks like Gatsby and Next.js.

Hosting the site with Netlify

Once we found the framework, it was time to figure out where to host the site. We could have hosted it on its own server or deployed a container, but our team is small, and we wanted to avoid the overhead of maintaining and monitoring our own infrastructure. Netlify was a good fit for us as their product is designed for Jamstack apps, and they had one killer feature (more on that later). It also helped that our Twilio Console team had recently completed a large scale migration to Netlify.

Securing the site for internal users

The last hurdle, however, was figuring out how we were going to secure our site and limit access to only Twilio engineers. How do you secure a site that’s just static files? You can’t secure it using JavaScript on the client, because anyone could use a tool like cURL and download all of your static content. We needed something server-side, but we didn’t have a server.

Thankfully, Netlify provides a solution called role-based access control with JWT. Simply put, you can restrict access to your site to only users that can supply a properly signed JWT. This verification happens in Netlify’s infrastructure, before any request can be passed on to your site.

Wiring up Okta, Twilio’s enterprise identity provider

Perfect. Now we just needed to wire up Twilio’s internal Okta identity provider to provide the necessary JWT. This was a bigger challenge than we expected, as the JWT provided by Okta’s “SPA” application type uses the RS256 algorithm, but Netlify expects a JWT created with the HS256 algorithm.

Thankfully, Netlify support had the great idea of writing a Netlify function to take the Okta JWT and transform it into a JWT that would work with Netlify. Here’s a simple flow diagram:

Okta posts an RS256 JWT to a function on Netlify, which transforms it to an HS256 token, sending it to the browser as a cookie. It also redirects the browser to the home page. For all subsequent requests, the browser will send the JWT cookie to Netlify to authorize access.

It worked great! But what if a user requested a direct URL for a specific document? We’d want them to be redirected back to the document they wanted after authorizing them. So, we made another revision to our function, which now followed this more complicated flow:

The browser requests a specific document, /docs/foo. Netlify will redirect them to Okta to get authorized, but also set a cookie indicating the original URL requested. Then, the normal flow from the previous diagram is repeated to authorize the user, but once the user is authorized, they are redirected back to /docs/foo.

That worked, but we wanted more.

Netlify’s killer feature (spoiler alert: it’s Deploy Previews)

Netlify has a feature called Deploy Previews. It gives you a unique URL for each pull request in GitHub, allowing you and your team to see what the site will look like with the proposed changes. Okta doesn’t support theoretically infinite URLs, so accomplishing this was going to require funneling the authorization flow through the production site that Okta did know how to talk to. Are you ready for this flow diagram?

The flow includes the same components as the previous flow while using the primary site as a proxy to Okta. The JWT is exchanged between the primary site and Okta, then the primary site passes along the JWT to the preview site.

Needless to say, this was a fair amount of code and required meticulous testing to ensure all the edges and corners were accounted for. But it worked, and our content authors (who are all engineers) are thrilled with the workflow.

Sharing the goodness

Just as I was thinking “I bet other teams could use this,” I got pinged by a colleague asking me how we did the Okta authentication with a Netlify site 😂. Originally, they were going to copy all the code that I wrote into their own Netlify site, but now that we have released the netlify-okta-auth package, they only need a few lines of code:

auth.js

const { getAuthHandler } = require("@twilio-labs/netlify-okta-auth");

const config = {
  jwtSecret: "super_secret_dev_only_value",
  prodBaseUrl: "http://localhost:8888", // update this as necessary
  oktaUrl: "TODO", // we'll get this soon
};

exports.handler = getAuthHandler(config);
exports.config = config;

login.js

const { getLoginHandler } = require("@twilio-labs/netlify-okta-auth");
const { config } = require("./auth");

exports.handler = getLoginHandler(config);

You can see the full installation tutorial for how to deploy this code, but the point is, it’s much simpler now.

Using the new package

We hope there will be those of you who will be able to take advantage of our work. In short, the advantages of using this new open-source library over rolling your own code are:

  1. Reduced complexity. You don't need to maintain your own Netlify functions to integrate with Okta.
  2. Helpful docs. This tool was originally built for an internal docs site by folks who love great technical docs.
  3. Netlify preview site support. In addition to the primary site, this package provides security for Netlify's deploy preview sites.
  4. Production tested. This package is used actively at Twilio for protecting internal documentation sites.

So go pick up your favorite Jamstack framework and start building some internal sites! Hopefully, netlify-okta-auth can help.

David Prothero is a Principal, Product Manager working on internal product docs at Twilio and a 6-year Twilio veteran. Before focusing on internal docs, he was the Senior Engineering Manager for the twilio.com website and, before that, a Developer Educator working on Twilio's customer facing documentation at twilio.com/docs. Prior to joining Twilio, David had a long career as a software engineer and engineering manager. David lives in the California Central Valley with his wife, two teenage boys, and two dogs. You will often find him behind a dungeon master's screen, running D&D adventures for friends and family.