What have I discovered when building Musicn?
Security (of user data and JWT), and React

Self-taught Software Engineer from Singapore (that eventually goes to school for it). Passionate about building new stuff that helps people save time!
Search for a command to run...
Security (of user data and JWT), and React

Self-taught Software Engineer from Singapore (that eventually goes to school for it). Passionate about building new stuff that helps people save time!
No comments yet. Be the first to comment.
My stint with Apple Music has come to an unfortunate end. I’m not trying to make it sound like a huge breakup note reveal. I’m actually writing this to reflect on my time with both services. It was an

Why my RAG system failed using ChromaDB and local embeddings — and how better context and data structuring fixed retrieval accuracy.

How we used Roblox Studio and Lua to build a 3D cybersecurity CTF game for students — and what we learned from bugs, refactors, and live demos.

Is Swift worth learning for React Native developers? An in-depth comparison of SwiftUI, SwiftData, DX, performance, and ecosystem maturity.

How I built a personalized graduation website with Next.js, Redis, access codes, and a server-side countdown to stop cheating.

I had this long desire to create a web application that allows people to see what I listen to on Spotify. I have had several attempts at it. Until I made Musicn. Musicn allows a Spotify user to sign up for an account and have their own Spotify profile to share with others. When others click the link, they can see their current listening, top songs of the month, and recently played songs.
I knew I wanted to use a relational database. I was introduced to the concept of a relational database in the previous semester in school, and I wanted to get my feet more wet. Since I'm a student, I wanted to go cheap since I'm broke and have no money ðŸ˜.
I settled on Supabase just because it's PostgreSQL, user-friendly because you can insert into the database with just four lines of code without typing any SQL and comes with a table editor in its online dashboard.

I used the official Supabase library for Javascript and realized that database requests take long (around 200+ ms per query). The issue became apparent to me while I was doing Authorization, and I realized that if I have no credentials, it rejects the request in a mere 7ms. However, with credentials, it had to do some queries, resulting in 200+ ms of query time!

I knew something was wrong because the query times for the database should be way shorter than that (based on my school final assignment for the year).
I made a huge realization. The realization is that the Supabase library fetches the Supabase API, which takes around 200+ ms to resolve, and it all started making sense. So instead, I used a library called pg. And my query times are shortened to 90-100+ ms. Sure not a big difference but after several testing, I concluded that the difference it made to the Heroku deployment is 46.8% faster!
Security plays a massive role in Musicn since it is hosted publicly for anyone to use. The data that are used and collected are:
It's essential to keep these data locked away and secure. In terms of obtaining user data, I took extra measures such as:

How Musicn works in terms of Proxy API to Spotify Web API
Using Supabase Javascript Library

Using pg Library

Note how the fetch request for nabil is way faster (1.18s vs. 558ms) (ignore the top_playing and currently_playing fetches because that uses Musicn as a Proxy API for Spotify Web API)
Musicn allows users to edit their profile by heading to the Profile page. Users can change their username so they can visit their friend's profile by going to a link such as https://musicnapp.herokuapp.com/user/nabil so hence it is a must to store the JWT token somewhere as part of its front end so that we can send requests to the backend for Authorization to the Profile page.
So I searched online to get some idea on how to store tokens securely because, in my previous assignment, we stored it in LocalStorage, and it just screams SECURITY BREACH to me! For those who don't know, storing JWT or anything remotely "secretive" in the LocalStorage is a big no-no!
After countless hours spent watching excellent talks by developers, I settled on using cookies. At first, it alarmed me because it is stored on the browser, but you can set some parameters to make the cookies way more secure upon further research. You can read this excellent article written by Ryan Glover explaining more about implementing safe cookies.
res.cookie("cookie-name", {
httpOnly: true,
secure: true,
...options
})
For my explanation, httpOnly cookies do not allow the browser to access the cookie via Javascript code.
Like what they say, security is obscurity, and that means not letting the attackers know what your application is built on or what database it uses. But Ironically, Musicn is open-sourced, and pretty much the world knows it's built on
But if you're building an actual world application, you can remove the x-powered-by header, which tells the attacker what framework you are using, and using the backend as a proxy to APIs make Musicn somewhat more secure (because no keys are exposed)
One group of developers builds the backend and the frontend separately, but I was dead on making the backend and frontend run on the same domain.
In the building phase, I used fetch in the React application to fetch API requests. It went something along the lines of:
fetch("http://localhost:4000/api/user")
And then it dawned on me. What if I changed the port number? What if I want to change the host? Well, adding a variable may help. Something like:
const host = "http://localhost:4000"
fetch(host + "/api/user")
But that means I have to write the host variable at every component file I created. Another alternative you could do is to export the host variable out of a single Javascript file but it became troublesome every single time I switch between development and production. Do I have to find my way to change the value of host?
That is when I found "Proxying" in React. Since I know that my React app will run on the same host and domain as my backend, I can proxy every fetch request to this host defined in package.json in the React project folder.
...
"proxy": "http://localhost:4000"
} // EOF
From then on, all my fetch requests can look something like this
fetch("/API/user")
So every fetch request in development will pass it through to http://localhost:4000, and later in production, the proxy value is discarded and will pass through the domain.
You can read more about what I've talked about here
Creating Musicn is a wonderful journey. I researched how to make my application way more secure and pleasant to use. Here are some take-aways:
httpOnly and secure options.