Back to Basics
I’ve been out of commission for the past few days with what would turn out to be a pretty severe ear infection turned sinus infection turned migraine inducer. Something incredibly frustrating about being sick is my mind going a mile a minute, but my body having zero capacity to keep up. A combination of pain, nausea, and exhaustion has made it extra hard to focus on much for long. But… this has given me time for some reflection.
I’ve been working on a homelab for a hot minute now. It’s coming along piece by piece, but it is far from done. One of the first things I wanted was some form of an authentication provider. So I grabbed authentik, spun it up, and started working it into a homelab. It works perfectly with the few services I’ve spun up, but I also needed to integrate my hand-crafted apps with it.
For a homelab, there’s a lot of places where you can forgo authentication. If you’re the only person using a service and it is not ever exposed to the internet, you don’t need authentication. Your computer’s log in credentials are essentially acting as your app’s authentication and authorization layer. If you have a service behind a VPN, you don’t need authentication in your app. The VPN is providing that security. And you are securing that properly, right?
All that being said, you should ensure your application is secure. Do use reasonable standards for hardening Dockerfiles, securing internal services, and making sure no one can get into your servers through a backdoor.
Now if you do want to expose a service to the internet, you need auth somewhere. And I have a little service that I want to share with some friends. It’s nothing big or complex, but I don’t want to make them get a VPN, I don’t want to use Auth0 or another hosted identity provider, and I don’t want to add multiple log ins to their list. I’ve seen how they manage log in credentials and it scares me.
No problem, though, right? I’ll spin up a new instance of Authentik just for my friend group, throw that in a VPS somewhere, and then use that for my identity provider. The couple of services that I want to share with them can just use Authentik and they’ll only need to remember one password. Or better yet, zero passwords and just do some magic links!
And yeah, this is the way to do it. So I started up this project. This first prototype, which is not presently accessible (I’m bad about not working with the garage door open), is just a prototype. I’ve got some vague notion of what I need to do, but there’s a bunch of questions on how I want to do it. For now, I have a Hono (+ Bun) API, SQLite for a DB, and a React frontend.
Herein lies the problem. I need to set up OAuth for this. I’ve done OAuth plenty of times for plenty of apps. There are many packages for this, of course. But they don’t quite suite my needs and many are a bit immature. AuthJS (formerly NextAuth) is a great library, but it’s still in the sub v1 area. They don’t yet provide a Hono package, but Hono does have a AuthJS middleware in their repo. But, needing a 3rd party middleware for a 3rd party package that is still in very active development is asking for trouble.
But I don’t need this versatile solution. I’m only supporting one particular identity provider. I can just write my own middleware. Wait, actually, how does OAuth work?
The Actual Problem
Several paragraphs in and we’ve gotten to the meat and potatoes of the problem. I don’t actually understand OAuth. That’s not really true, I understand the core principle behind it, but I don’t know how to do myself.
In JS land, we tend to use packages and frameworks that other people have written, and with good reason! Imagine trying to rewrite something like Tanstack Query and keep up with deadlines. There are multiple people who’s fulltime job is working on frameworks like NextJS and Remix; I’m just one dude with clients who want things fast and bug-free. There are somethings I can reasonably reinvent - 20 line hooks don’t need to be a dependency - but most of what we rely on can’t reasonably be rewritten.
So, we happilly run npm install react react-dom @tanstack/react-query @tanstack/router @radix/react-dialog @radix/react-select zustand immer react-tracked react-hook-form clsx tailwind-merge cva
.
Sure, you can go read the source code, and you should. But I don’t learn much by reading. I need to do.
The Doing
My goal for this is pretty basic. I’ve got a handful of topics that I want research and properly learn. Using these developer roadmaps, I’m creating a battle plan for tackling these complex topics.
It’s a little hard to figure where exactly I want to start. OAuth is top of mind, but a deep dive on databases might be more valuable. All of databases is too big of a chunk, though, so I’ll need to figure out where the actual entry point lies within that.
Once I have an understanding, I’ll do some building. I might start with just finding some packages that I use regularly, diving into their area of expertise, and building out a simple version of them. For example, building my own version of AuthJS, but, you know, one that only works for a very small use case and likely isn’t feature completely.
Honestly, that’s all up in the air. The only outcome might be a blog post. The goal is not to get bogged down building something that fits all of my needs, but something to building something that I can learn from. I might toy with building my own database - that sounds fun - but I’m not going for anything novel or feature complete.
I’m planning on using Go for backend-y things, maybe some Rust as well. Frontend is TBD; might be something like Solid or Svelte that has less third-party support, or it might be sticking with React since a lot of the frontend-y packages I use are specific to React. We’ll see.
Ultimately, I want to become a better full stack dev. I don’t expect to become a master of any of this, but learning the basics will make it easier for me to evaluate third party dependencies, create abstractions, and generally just actually be a reasonable mid level developer.
I’m going to (lightly) hold myself to writing a #back-to-basics
post every month-ish. I’m not going to beat myself up about it or hold myself to unrealistic deadlines. Sometimes work uses all of my active developer brain cells, and that’s okay.
So, the only way to begin is by beginning. Here we go!