DEV Community

Luca Castelnuovo
Luca Castelnuovo

Posted on

Custom central access manager

When I came across products on the "web" which seemed really useful but weren't free (A student-budget isn't that big), I would try to build it myself, thus saving me the costs and giving me the opportunity to practice.

The old way

To keep these projects as simple as possible I used GitHub OAuth. Which was really easy and great for that time. But once I had about 3 of these self-made projects and a few modified forks using GitHub OAuth, I started to think that it wasn't practical to update all these repo's individually if I changed the auth logic.

GitHub flow

The bad fix

I had created my own OAuth provider and client.

GitHub logo Luca-Castelnuovo-Archive / Accounts

OAuth Server for the authentication of my personal projects


But I didn't like it. Mostly because the code wasn't well written, didn't follow the guidelines for OAuth and I didn't felt that I could keep maintaining this spaghetti code, making it obsolete in the near-future.

Custom Flow

The solution

So I came to this project. It was important, and an oversight of the earlier project, to define what I wanted the project to achieve, how to achieve this, and actually achieving it.

The defining part

It thought it would be a good idea to still have the central authentication and authorization concept, while maintaining the simpleness of GitHub and Google OAuth.

I had been experimenting with JWT's in this time, so instead of my provider granting authorization_code, I would send an JWT with claims to login. The client could then validate the claims and provide access.

During this process I realized that I wanted to provide multiple levels of access. This is where the variant claim comes in handy. The claim would limit certain things, like the allowed monthly API requests, files upload limit, etc.

The how-to part

For the authentication I would use a mix of three sign-in options. GitHub because I use it the most. Google, because most non-github users probably do have an Google account. And finally email.

Now I was pondering whether to include email, because this means implementing forgot password, verify email, and storing passwords problems. Luckily, I came across couple of posts about magic-login links, but some raised concerns like this one.

Login Screen

These concerns are a bit outside the intended scope of this article. But come down to email isn't that secure. To fix this I coupled the login link to the browser session. This had the problem that the link couldn’t be accepted on your phone and then continue on your desktop, but this was a comprise I was willing to make.

With the authentication sorted, the authorization part came.

For this Gumroad seemed like a useful solution. I would create a hidden Gumroad product for each service. These would contain tiers (variants).

Gumroad service

On successful purchase Gumroad would provide a license key which I would store in my app and use the authorize a user’s access to that service.

Licenses screen

Now that I was able to authenticate user with login options and authorize user with connected Gumroad license, the final part came, integration with the clients. The client would receive the login token as JWT containing the following claims:

{
  "iss": "https://apps.lucacastelnuovo.nl",
  "aud": "https://mailjs.lucacastelnuovo.nl",
  "iat": 1590227858,
  "exp": 1590228458,
  "type": "auth",
  "sub": "9ea3cbd8-895a-4f9b-ac69-5f600376adbb",
  "user_agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3",
  "user_ip": "151.101.130.217",
  "variant": "Professional"
}

These tokens would be valid for 10mins, to mitigate token theft impact.
I didn't want to use refresh_tokens as this would just create another unnecessary (for this system) attack vector. Instead the following flow is implemented:

Apps Flow

The building part

To build this project I was thinking about using Laravel or another framework, but these were all quite complicated to learn quickly enough I wanted this project to be done (presentable at the least). So in typical side-project fashion, I created my own framework. Which took maybe more time to learn the basics of Laravel, but also learned me a lot of things.

GitHub logo Luca-Castelnuovo / CubeQuence

Ultra-Light custom php framework

The final stack I used was:

  • Server: LAMP
  • Backend: CubeQuence (PHP)
  • Frontend: HTML, CSS (MaterializeCSS), JS (vanilla)

Links

Demo: https://apps.lucacastelnuovo.nl
Code:

GitHub logo Luca-Castelnuovo / Apps

Centralized auth server for managing access to my apps

Additional Thoughts

It was really fun to write this article, i'm not really a writer so this was a difficult but educational experience.

Top comments (0)