Dev Joy: Making Authorization for Internal Web Apps Simple
I have fought with oauth or kludged basic auth for so long, and neither have made me happy. No more! We devs can leave that in the past. Here is my new way to build a small, simple internal web app:
Step 1: Pay Cloudflare $0 for 50 users. Seriously, you can set this up for free. Add a domain name “mydomain.com” that Cloudflare must be DNS authoritative for. (Sorry, you can’t add a subdomain like devs.mycompany.com on their free plan. They have to be authoritative for a 2nd level domain.) Now the cool thing Cloudflare can do is proxy HTTPS traffic to that domain. Cloudflare Zero Trust can additionally force an authentication to IDP(s), and authorize only users you have allowed, before sending the request to your application origin, along with a simple JWT .
Step 2: Pay AWS $1 for 300 million HTTP API requests. (Plus Lambda costs, etc.) Unfortunately their built-in JWT authorizer won’t work, but it’s not too difficult to write your own custom Lambda for this. You need to validate the JWT was signed by Cloudflare, and that the audience is for your application. (app1.mycompany.com has a different random audience string than app2.mycompany.com, or app.other-company.com) Luckily, you can deploy a single Lambda Authorizer for all applications — you just need to configure the audience as a stage variable, which is passed to the Lambda authorizer. Sweet!
Note that all unauthorized requests will NOT MAKE IT INTO YOUR VPC. You know those random hacking requests you see in a publicly open NGINX server? They will be rejected by the Lambda authorizer, and can’t DOS or touch your origin — assuming you’re using security groups (VPC Link) or IAM to secure it. (And for the truly paranoid, try enabling mutual TLS between Cloudflare and AWS API Gateway!)
Step 3: Your application can know which user is making the request, by simply looking at a HTTP header to see the user’s email address. This header should be set or validated (CF-Access-Authenticated-User-Email) by the authorizer Lambda, from the trusted email address inside the JWT.
Step 4: Sit back and … profit? Honestly, I thought this would be a longer article. This architecture makes it too simple: managers can add and remove users to groups or applications using the Zero Trust web interface (even contractors who have no trusted IDP at all can get a one-time email code), and devs just build applications and verify a JWT.
We are also looking at putting our Jenkins servers (sigh) behind Zero Trust, using Cloudflare tunnels. The tunnels mean that no inbound ports are open on the servers.
Finally, authentication and authorization might be getting simpler! I think this shows the true power of “separation of concerns”. Yes, you are trusting Cloudflare to decrypt your traffic, but the benefit is they take care of a lot of headaches. If you have alternatives, leave a comment!
PS: If you’re an enterprise already using SSO, with dedicated admins, good for you — this article is for one-dev setups. We’re usually ignored, but we exist!
PPS: My two-proxy diagram made me think of this meme ;-)