Authentication is a very important part of any website. It's the thing that protects your users' data, and it's also the thing that, if implemented incorrectly, will kill your startup before it even begins. 😶
However, there are many well-known authentication solutions that can be used for your startup because they will save you time and prevent risks to the success of your business - provided you choose the right one 😅
Backstory
When I started my startup MakersDiary, I decided from the outset that it made more sense for me to use an established solution - even if it costs money.
MakersDiary is the first platform designed specifically to help indie makers and developers to share their journey in public. Track and manage their side hustles and startup projects to share all relevant information, successes, and struggles with the build-in-public community.
For authentication, MakersDiary started with AWS Cognito via Amplify, a great choice for a small startup that will be a serverless web application. I was using the Cognito User Pools, an authentication provider that allows MakersDiary to use a user pool with the AWS credentials of each user. When users sign into their account, they are redirected to my serverless web application that can handle all necessary needs.
The Cognito Problem
In the beginning, Cognito was really easy to set up but as MakersDiary got more complex I started to struggle with this solution. AWS is awesome but also very complex and extensive with a very steep learning curve.
Problem 1 - ❌
It can happen that you lose yourself very quickly in the configuration and implementation so that everything works as desired. While I really love doing heavy implementation and learning more to be able to code what I want, it didn't help when I want to release my product quickly.
So you have to develop and maintain your own backend service running on AWS Lambda that will handle the user auth process including pre- and post-auth functionalities like sending nice looking welcome or signup-confirmation emails. This is quite a big effort especially if you don't have such experience.
Problem 2 - ❌
The next problem arose when I started to implement third-party authentication like Twitter. With MakersDiary users can share their project information, monthly revenue & user updates, and much more directly on Twitter.
While Cognito is a great solution for setting up your own authentication, it has almost no support for third-party authentication (except for Amazon, Apple & Google). So I had to implement the Twitter OAuth process by myself for MakersDiary.
Even if there are great libraries like passport.js or twitter-api-v2, the manual implementation is still very time-consuming and gives me quite a headache.
For example, after a user authenticates with Twitter all necessary information has to be written into the AWS Cognito User Pool so that you have all such information within your JWT token on your client to show e.g. the Twitter handle, name and profile image. It is all absolutely possible but a bit tricky and complex. 😪
Later I realized that MakersDiary should support other social media providers e.g. LinkedIn beyond the MVP, so I'll have to implement this functionality again by myself.
Problem 3 - ❌
MakersDiary users can upload their profile images, project logos and screenshots to add them to the projects they create. For this case, I used an AWS S3 bucket storage. If you just need a public bucket without any restrictions S3 is very easy to use. But if you want to restrict access to certain AWS accounts, S3 becomes very complex. In my case, I needed to restrict access to some specific JWT token holders with my AWS Cognito users, IAM roles and policies. And here the pain begins 😅…
The Decision
After I while I saw more and more problems here which will block or at least slow me down sometimes. I was thinking about AWS Cognito is may not that easy and suitable solution for a small one-man startup.
At this point, MakersDiary was not yet released, and no users had signed up. This made it easier for me to migrate away from AWS Cognito to another auth service than if I did so later with active users.
So I decided to search for another auth service.
My first idea was to move to Auth0 one of the biggest auth services out there. But the Auth0 pricing model is very expensive at a later stage of your Startup and after reading Kevin Grüneberg's article about how Parqet had to migrate from Auth0 to Supabase for that reason, I investigated further.
Why Supabase?
Supabase is an open-source alternative to Firebase. They use the slogan "Build in a weekend. Scale to millions" and I can say that is not a lie 😃.
It allows you to set up the top 3 main parts of your app in almost no time.
- Authentication
- Database
- Storage
You can start with Supabase with a free plan which is absolutely suitable for a young startup. If your startup grows you can upgrade to a fair-priced pro plan without any problems.
What I really like about Supabase is its simplicity. You can set up the whole app in one day with just a few lines of code. This means that you don't need to spend a lot of time on backend development and can focus on building your app. It's also open source so you have full control over your data.
Problem 1 - ✅ Solved
I planned to release MakersDiary in around 7 days so the decision to move from Cognito to another auth service could put my whole release at risk. Luckily Supabase has quite nice documentation and initial database scripts so setting up my first project was no problem.
Once you become familiar with the dashboard's initially confusing navigation, setting up everything becomes very easy. 😁
In my case, I just needed the auth service and some databases to store the user and the user's profile information. All my other databases will stay on AWS DynamoDb.
So I added an email/PSW auth flow for MakersDiary with a post auth confirmation email. In the Supabase free plan, you can have up to 50.000 active users - a number that should be sufficient for most small startups. I would be thrilled to have such a large amount of active users for MakersDiary 😎.
//User sign up
async signUp(signUpObject: any) {
return await this.supabase.auth.signUp({
email: signUpObject.email,
password: signUpObject.password,
options: {
data: {
//Some meta data e.g.
//first_login: true
},
},
});
return { data: data, error: error };
}
//User sign in
async signIn(email: string, password: string) {
return await this.supabase.auth.signInWithPassword({
email: email,
password: password,
});
}
//User sign out
async signOut() {
const { error } = await this.supabase.auth.signOut();
if (!error) {
this._session = null;
}
}
Supabase supports Trigger functions for any database row manipulation. So you can trigger a DB script in PostgreSQL Structured Query Language (PL/pgSQL) when e.g., a new user has been added or the profile of an existing user was updated.
BTW: Supabase provides an easy way to create and customize HTML email templates for all types of emails.
Problem 2 - ✅ Almost solved
Unlike AWS Cognito, Supabase supports all major social providers so that you can offer your users to sign in with any of them - with only a few minutes of setting up and a few lines of code.
async signInWithSocial(provider: string) {
return await this.supabase.auth.signInWithOAuth({
provider: 'twitter',
options: {
scopes:
'tweet.read users.read offline.access tweet.write follows.read like.read like.write list.read list.write tweet.moderate.write',
redirectTo: 'https://example.com/welcome',
},
});
}
The little fly in the ointment was that Supabase hasn't supported Twitter Apiv2 for that long, so the use of it doesn't seem to be well documented or I just didn't find it in a short time.
So the Twitter sign-in was working well, but I had problems getting all the information - Twitter Apiv2 accessToken, accessSecret and refreshToken - that were needed for my server to use later for making calls against that service.
But I didn't mind that because my own implementation of the Twitter OAuth sign-in process was working well so I used that again. 😅
But now I'm prepared for a future where MakersDiary can be accessed through several other social media providers.
Problem 3 - ✅ Solved
My third pain point was finding a storage solution where authenticated users can upload and access files and if necessary generate signed URLs to share them in public.
Supabase allows you to store 1 GB of files for free, which should be enough space for the first profile images and project logos.
I love how easy it is to store and update files, as well as generate public URLs from your client application with a few lines of code.
//Upload avatar image
private async uploadAvatar(file, filepath) {
return await this.supabase.storage
.from('avatars')
.upload(filepath, file, {
cacheControl: '3600',
// upsert is set to true, the file is overwritten if it exists
upsert: true,
});
}
//Download avatar image
private async downloadAvatar(filepath) {
return await this.supabase.storage
.from('avatars')
.download(filepath);
}
//Creates public url
private async getPublicFileUrl(storage, path) {
const { data } = this.supabase.storage.from(storage).getPublicUrl(path);
return data.publicUrl;
}
Conclusion
I didn't go too deep into technical detail here because it would be beyond the scope of this article.
I'm really happy with my decision to move from Cognito to Supabase. The new MakersDiary auth process is easier for users and allows me to expand without putting more stress on myself - something I couldn't handle if the site's growth with Cognito and S3.
Even if supabase is still at the very beginning of a great journey, it is already a very big help for small startups and side hustles. Next week the new release of Supabase will launch and I'm looking forward to which new great features will be added. 🙂
I hope that this post helped you understand how I solved the three main pain points of my project and made it better for everyone.
If you have any feedback or questions, please let me know in the comments!
Special thanks to Kevin Grüneberg for his help in troubleshooting my first attempts at creating PL/pgSQL scripts. 😁💜
Top comments (1)
Wow, I'm just doing this process as of 2 days ago with the same situation as you! Literally I've been working on a project for around 6 months now, and decided to completely ditch Amplify in favor of Supabase, and in this 2 days I've been able to duplicate around 60% of all the work that I did on Amplify that took me months!