Building auth for a multi-tenant PaaS

This time I started building the auth foundation for Uploy…

The main idea across these commits was pretty simple: I wanted users to be able to sign up with email + password first, then I wanted to harden the flow a bit with rate limiting and sliding sessions, and finally add GitHub + Google OAuth2 for social login.

I should admit… I probably over-engineered this part a bit early. I added things like rate limiting and workspace handlers right away, even though the app is still in a relatively early stage. But that instinct came from my previous work in 2025, where I had already built a multi-tenant application before (see the red arrow in my portfolio below), so tenant/workspace concerns were already sitting in my head while I worked on this.

Fullstack experience 2025

In this commit and this commit, I added the basic auth system using email and password. Users can now register, log in, get a session, and access protected routes.

There were a couple of small decisions here that are worth mentioning.

For password hashing, I used Argon2. My reasoning was honestly pretty simple… OWASP mentions Argon2id and explains that Argon2 was the winner of the Password Hashing Competition in 2015, so that felt like a strong enough signal for me to use it here. If you want the deeper security reasoning, the OWASP page is worth reading.

I also created a workspace automatically during registration by splitting the email before @. So if someone signs up with wahyu@email.com, the first workspace name becomes wahyu. This is obviously not the final design and probably not the best long-term approach, because later I want proper workspace creation as part of onboarding. But for now, it was a simple way to connect auth with the multi-tenant direction of the product.

Outside of that, the rest of the work was the usual auth plumbing: register, login, session creation, MeHandler, middleware, membership, and the other pieces needed to make a multi-tenant PaaS feel more structured.

Here’s the demo video…

After that, in this commit, I added a sliding session model.

Before this, I was setting the session cookie with a fixed MaxAge of 7 days. That means once the browser had stored the cookie for 7 days, the user would have to log in again to get a fresh session, even if they were still actively using the app. So I changed it to a sliding session, where the session lifetime keeps moving forward when there is activity… but not forever.

That trade-off felt more reasonable to me. Active users do not get logged out too aggressively, but the session still has an absolute lifetime so it cannot be renewed indefinitely. I liked that balance, and it also matches the kind of trade-off OWASP talks about when discussing session lifetime decisions.

Finally, in this commit, I added Google and GitHub OAuth2 social login.

At this point, the auth flow started to feel much closer to a real product. Email + password is still there, but now users can also choose a more familiar login path through GitHub or Google, which feels especially natural for a developer-facing product like this.

Here’s the demo video…

© 2026 Wahyu Syahputra. All rights reserved.