Identity Management Solutions, Part II: Firebase Auth, Supabase, Keycloak, Auth0 & Ory Kratos

Rating: 5.00 / 5 Based on 7 reviews

Selecting the best identity management solution is hard. There are a multitude of options available on the market, each with its own pros and cons. We compared the most obvious choices with the less popular ones. Read on to see our comparison of Firebase Auth, Supabase, Keycloak, Auth0 & Ory Kratos and what the best identity management software is for us.

As was said in the previous part, Identity is not an easy thing. There are multiple (valid and… less valid) ways to implement that; there are standards that should be followed. At LeanCode, we have a diverse set of clients - from small startups to large corporations - and each of them has unique requirements on top of that. Finding a one-size-fits-all solution is not an easy task. An impossible task, I would say. Fortunately, there are products that tick more boxes and that give us enough flexibility to have an answer to most of our needs.

Here, you can also find our earlier article from this series:

The backstory

Up until recently, we did identity management ourselves for every project. We didn’t do password hashing nor JWT token issuance ourselves; of course, we used ASP.NET Core Identity and IdentityServer4 for that. But we did extend them, and we did introduce our own flows for different kinds of sign-ins (we did socials, we did phone number + SMS code sign-ups, we did magic links). It was great, but we found out that we did everything over and over again, each solution being different in only the most minor details.

Some time ago, we decided that it was high time to standardize our identity management approach and work out a solution that would solve our most common cases without any hassle.

What about our previous approach?

We love IdentityServer. We don’t hate ASP.NET Core Identity. They work together nicely and allow you to accomplish great things. IdentityServer gives you a great OAuth2/OIDC-compliant server, and ASP.NET Core Identity gives you a model of users/roles/claims/etc. Unfortunately, this means they are quite low-level. You have to implement most of the things on top of them yourself. If we need to do a custom authentication/authorization, Duende Identity Server will be our go-to approach, but for all other purposes, we need something simpler to implement (or rather - not implement at all).

Our criteria

We don’t have unreasonable expectations. And yet, we didn’t find a solution that would check all of our boxes. Fortunately for us, we were able to find one that solved almost all of our problems.

Here are the main things that we looked at when choosing the right solution:

  1. We need email+password sign-in flows,
  2. We need seamless socials (Google/Apple/Facebook, at least),
  3. We want to have biometrics sometime in the future (both on web & mobile),
  4. We need to be able to customize the solution to some sensible extent,
  5. We need to be able to control the costs,
  6. It would be nice to have both cloud & self-hosted options,
  7. We don’t need to be OAuth2/OIDC-compliant, we don’t need any kind of UI, but the solution should follow best DevOps practices.

Identity management solution comparison: tools we evaluated

There are multiple tools available on the market that are related to identity management. Some are more B2B tools, some are more B2C focused. Some scratch the surface of “directory services.” There are tools that have been with us for many, many years already and will stay with us for many years to come (looking at you, AD), but for our purposes, we want something simpler - we just want to manage the identities of the users of our app.

Still, even then, there are myriad tools available. There was no point in analyzing them all, so we selected a few that were the most promising and dug deeper. Here are the pros and cons of each of the solutions that we considered.

Firebase Auth

When it comes to auth solutions for Flutter applications, Firebase is the solution. However, we have a love-hate relationship with the whole Firebase suite, and Auth is no different. It is a great tool if you want to start the project, but it will bite you sooner or later.

There are a couple of reasons why one would like to choose Firebase Auth. First and foremost - it is very easy to integrate into any mobile app, Flutter included. You basically turn Firebase on (which is done for virtually every mobile app), use the provided libraries, and get a fully featured auth. It is also cheap at the beginning in terms of per-month maintenance cost - you get 50k MAU for free and then pay for every MAU. When growing, pricing is also somewhat predictable but can get quite high.

The main problem with Firebase Auth is that it is tightly coupled with all of the Firebase. If you want to use it, you basically have to opt-in to the whole suite. If you want to customize any flow, you have to do that with Cloud Functions for Firebase. If you want to store anything other than the basic set of attributes, Firestore is the recommended solution.

Firebase Auth is also limited in terms of its functionality. It is basically only authentication (with some authorization that can be done with Cloud Functions), without any profile/identity management. You have to implement it yourself (with Firestore, preferably) to get anything that resembles a user profile. Doable, but needs to be done yourself, without much guidance. This is simpler than doing authentication, we agree, but far from being the main feature of every product.

Also, when it comes to authentication, it is still somewhat bare-bones. You have some extensibility points that you can code against with Cloud Functions, but not much. Also, if you need to communicate with external systems, it gets quite tricky to do so without losing data if something goes wrong. If you limit yourself to Firebase functionality, I’m sure it will magically work, but you don’t have any help if you have to connect to the outside.

The provided sign-in methods are also limited. Yes, it has all kinds of “username + password” flows, magic links, and SMS codes sent to phones and socials (done best on the market when it comes to mobile apps, probably), but when it comes to some newer ways like biometrics or hardware keys, you are left without much luck. It probably is on the roadmap, but we don’t know that, as the roadmap is not published.

When it comes to pricing, it feels cheap. And indeed, it is - 50k MAU for free, then no more than $250 for an additional 50k (paid for every single user, not in bulk). It’s quite cheap. It gets much more expensive if you need to use some other OIDC/SAML provider (e.g., client’s AAD tenant), but fortunately, that is not mostly the case in B2C apps.

It is also worth noting that Firebase Authentication can only be hosted in the US - this means that it might be somewhat hard to make it compliant with GDPR requirements. Even though it might be possible to prepare a Privacy Policy so that it is in agreement with privacy regulations even though user data (and here we almost always talk about Personally Identifiable Information) is exported to the United States, for us, it is totally unjustified. Google Identity Platform, the underlying platform of Firebase Auth that can be used directly, also seems to have the same limitations.

Last but not least, Firebase Auth docs are clunky. They are quite mixed up, show you only basic solutions, then don’t elaborate on why you would like to do things that way, and sometimes just miss the points. This clunkiness also applies to the admin panel. There probably is everything, but finding things is hard. And you have no declarative option (the Terraform provider is… mediocre and does not have support for Auth yet), so clicking is the only way.

A note on pricing

I say that Firebase Auth is quite cheap, but that is relative to other cloud providers. For example, their pricing example says that for 225k MAU, you pay around $860 or $0.0039 per MAU. This is not that much, as you will see later, but still expensive if you compare that to the self-hosted options, which can go much, much lower.

Auth0

Auth0 is one of the most well-known and widely used identity management solutions that focus on end-users. They are also one of the oldest SaaSes in this market. This means that their solution is rock solid and known by many.

And indeed, it is rock solid. All the features that I described above are supported by the product. They have all conventional flows implemented (with both memorized passwords and OTPs), they support hardware keys, and they support biometrics. If you need 2FA, you have a slew of options. They support basically every kind of “standard” flow.

When it comes to customizations, they have a thing called “Actions.” Basically, it allows you to run JS code when something happens. This is different from the Firebase case because here, “Actions” have a single purpose - extending the flows, nothing else (and that’s a big thing). You can do things inline (which will be most of the time), delegate things further by doing HTTP calls, or use any of the NPM ecosystem libs. This is basically a somewhat limited FaaS that works well with everything else.

Also, the place where Auth0 shines is the admin panel. It works great and helps you navigate myriads of configuration options. Nevertheless, Auth0 also has a Terraform provider that works OK. It’s not the best, but usable. The con here is that Auth0 is still mostly imperative, so the declarative TF approach needs… adjustments sometimes. There is also the Deploy CLI Tool, but that is still an afterthought.

There is no rose without a thorn, and Auth0 is no different. As with most solutions, it is web-focused, and that shows sometimes. The “default” way of signing users in on mobile is to use Universal Login, thus opening a WebView (or custom tab, or some other service that conceptually does web flow). It works but has mediocre UX. Fortunately, you can implement everything from scratch, but that requires some more digging and has much less description available. Also, in the case of Flutter, not everything is possible with the official SDK. It is being developed quite extensively (last time I checked it allowed webview-based sign-in only, and now you can sign in with username and password using your own UI), so I think it will start being… usable soon, but they’re not there yet.

When it comes to some bigger customizations, we won’t have any luck. Auth0 is SaaS-only; thus, you can’t modify anything major that would require code changes. Actions are great but still limited. You can’t implement your ideal flow, you can’t break the rules even if you really want to.

However, the main pain point of Auth0 is its pricing. Although it is great and works great, it is expensive. One-fifth of the free plan of Firebase auth costs around $1500 (or $0.15/MAU). I can’t even say how much the situation from the Firebase example would cost, as there is no public pricing for numbers this high. This is quite a deal breaker, and I think the main reason why we haven’t selected Auth0 as our main provider.

It is also worth acknowledging that Auth0 did a tremendous job educating people about authentication. Their documentation is fantastic not only in terms of Auth0 features but also in general authentication topics. You can find there a detailed description of protocols, reasoning why to use them, and when not to use them. This is really a treasure trove of educational content.

Keycloak

Now, onto the other big contender in the space - Keycloak, the open-source project sponsored by RedHat. It is also one of the oldest ones in this article, although according to Wikipedia, it is younger than Auth0. Nevertheless, since it is sponsored/maintained by RedHat, it is used by the biggest enterprises.

And it shows. Keycloak is big (relative to other comparable solutions). It is focused not only on end-users but also integrates well into enterprisey things. It integrates with all kinds of “old school” technologies like Active Directory, Kerberos, or LDAP. It supports multi-tenancy inside (which is not a given) a single instance. Allows seamless impersonation of users (which is quite rare, especially since most solutions don’t do fully-featured authorization, so cannot decide who is allowed to impersonate whom). And has an extension framework where you can modify almost everything.

This is also a (somewhat minor) drawback - the Keycloak seems complex. You have a multitude of extensions that work together to make the Keycloak usable, but theoretically, you can turn/remove everything. This opens the Keycloak for extensions but makes it hard to understand.

This model is also complex in other ways - to hook into any action, you have to develop a fully-featured extension (that is Java project). Even if you want to do something very simple, you will need to (correctly) create multiple files with a lot of boilerplate and then deploy it as a JAR file. For complex extensions, this might make sense, but if you need to develop something project-specific, then all the fuss is unnecessary.

The nice thing about Keycloak is that some things can be configured declaratively. Unfortunately, not all. Some runtime-like configuration entries (OIDC providers, for example) are dynamic. Thus, they require either clicking through the UI, using CLI, or going the Terraform way. It works but makes deployments more complex and less portable. Fortunately, the providers for Terraform seem to be in great shape, so the configuration might not be that annoying (although we haven’t tried them).

Also, it is worth noting that Keycloak is only self-hosted. There are some third-party managed solutions, but they are not official.

Other worthy contenders

Supabase

Supabase is an open-source alternative to Firebase. And just like Firebase, it has its Auth module. It tries to combine the functionalities of Firebase Auth and Auth0 to some extent. We used it, and it works great, but basically has the same conceptual limitations as Firebase. There are also some design decisions that are rather… unique and don’t really appeal to us universally, so it can’t be our go-to solution. We have an article about Supabase in the pipelines, where you will be able to learn more about it, and we will describe its pros and cons there.

Azure Active Directory B2C

Since we do most of our backend in .NET and we use Azure for hosting, we need to talk about AAD B2C. We are not fans, to say the least. 

The main pain points that we had with it are:

  1. Limited functionality when it comes to sign-in methods,
  2. No biometrics in sight,
  3. It’s far from being developer-friendly,
  4. We can’t self-host,
  5. Docs are subpar,
  6. This is a complex tool with walls of XML for configuration.

Microsoft is also introducing Entra External ID, which will be a successor to AAD B2C (or at least this is what I understand from the press release), so we will probably reevaluate when it lands.

Zitadel

This is one of the lesser-known ones. It’s also quite young (the first commit was made in March 2020, with a v1 released a year later). It aims to be an Auth0 replacement, but open-source and possibly self-hosted. It looks promising, it also meets or aims to meet all of our criteria. Unfortunately, it still has many rough edges, the docs aren’t great, and as with Auth0 and most other solutions, favors the web. We also don’t really look for an Auth0 replacement for exactly the same reasons that we don’t consider Auth0 our go-to solution - it aims to be easily integrated with everything based on clicking through the admin panel. We aim for something less clicky, more devopsy.

Our choice

As you could have probably guessed by now, the previously described tools won’t be our go-to choice. We tried to be as objective as we could be to select the best solution for us, but since we’re all humans, some subjectivity got into the process. Nevertheless, from now on, our default identity management solution will be quite a young contender on the market - Ory Kratos.

Ory Kratos

Kratos is an identity management solution. It is somewhat different from the others here. First and foremost - it is quite young, as the project started somewhere in 2018. This means we have quite a new codebase (in Go) that is maintained according to current DevOps standards. If you want to self-host, you get a small container that can be run basically anywhere. You don’t need to run any JVM, just a pure static binary working in a distroless container.

If you don’t want to host it yourself - you have an Ory Network for that. It’s basically Ory suite-as-a-service, hosted by their creators. It might not be as cheap as Firebase, but still quite reasonably priced. Since it is Kratos (et al.) underneath, you also can migrate into and out of the cloud basically at will, giving you the freedom to select the most suitable hosting option for you.

The main thing that sets Kratos apart from all the others is that it is API-only. It does not give you any UI. Any. There is a NodeJS-based self-service UI, but it works mostly as a reference, not a full-featured product. This works perfectly for us. As I said previously, we don’t need an “admin panel” - we prefer a declarative configuration, which Kratos provides (it’s YAML all the way, but that is better than clicking). 

We also don’t need “admin user management”, as clients rarely want to have to go to a separate app to do such a “simple” thing, and we need to integrate it with a more functional CMS either way. And when it comes to clients - we build new products; thus, the UI needs to look the way we want it to look. It might behave in some standardized manner, but the look and feel must be under our total control. Kratos, with its API-only approach, provides that!

What does Kratos provide when it comes to flows? Almost everything that we want. We have an email+password flow (with optional verification), there are socials, there is a generic “username + password” flow, and WebAuthN works (not on mobile yet, but we hope we will be able to add that soon). It also standardizes all the accompanying flows, like registration, email/password change, password reset, email verification, MFA changes, and alike. This gives us exactly what we wanted - some standard way of doing things (that we don’t need to come up with) but gives us control over how that works and how it looks (as we don’t have ready-made UI).

When it comes to customizability, Kratos delivers. Although it does not allow you to define code, it sends webhooks that allow you to react to some actions. For super simple apps, that might not be the easiest, but if you have your own backend, either way, this is, I would say, a natural way of integrating services. Also, when you need to customize something that is ingrained in Kratos, you can modify the code as you see fit. Just like we did recently (and we won’t stop there :) ).

Unfortunately, there are no silver bullets. Kratos is great; we love it, but it has its drawbacks. First and foremost (and we were this close to not selecting it because of this), it has bugs or missing features that make our lives somewhat harder. Nothing critical and nothing that we couldn’t live with, but still. Also, some features are not implemented the way we would like them to be. We probably will tackle some of them ourselves.

These cons aren’t great, but since we can contribute, in the worst-case scenario, and adjust everything to our needs on our own. We wouldn’t be able to provide all the other features that Kratos provides, so this seems to be a fair deal.

Ory Hydra/Keto/Oathkeeper

Kratos is not the only product in Ory’s portfolio. They also have a companion (or rather - Kratos is a companion for other tools, but that doesn’t really matter) that makes up for a modern authentication/authorization solution. This was one of the reasons for selecting Kratos - we get a small, focused solution for authentication and can integrate it with other products when the need arises.

Ory has three additional products:

  1. Hydra for OIDC-certified server with pluggable backend (Kratos by default),
  2. Keto for defining and evaluating access policies; and
  3. Oathkeeper works as an authenticating HTTP proxy that connects all the other three tools (or other tools, it is pluggable).

We don’t plan on using them by default, but knowing that we have a whole bunch of tools ready feels good. 🙂

Summary

This was a journey. We haven’t mentioned all the options that we considered. Otherwise, this article would be much longer. We can say with full confidence that selecting the identity management solution is an impossible task. Nevertheless, our aim was to select a solution that would work for us in most of the cases, and we think we found one - Ory Kratos. 

Among all the products, it has a set of unique features that give us, by default, all the constraints that we want to have and all the functionalities that we need. Two projects already use Kratos, and we have a few more that will start with it. We also created a Terraform module to deploy it, some smaller ASP.NET Core integrations, and a Flutter library that streamlines integrations, which we will soon publish. We do hope that it will be a fruitful future!

Also, we’re not done yet. There will be a Part III that describes how to migrate your ASP.NET Core Identity + IdentityServer4 solution to Kratos without losing any user data and another article that better describes Supabase and how it works.

If you still have any questions regarding Identity Management or developing your business mobile or web app project, you can order a free 30-minute consultation call with our experts.

Meet our expert

Let's schedule a talk!

Jakub Fijałkowski
Head of Backend at LeanCodejakub.fijalkowski@leancode.pl
Jakub Fijałkowski, Head of Backend at LeanCode
Rate this article
5.00 / 5 Based on 7 reviews

You may also like

With the changing landscape of identity management, at LeanCode we faced the challenge of selecting a new identity management solution that would be our default for the coming years. We want to share with you the whole journey. Find out more about our approach to this task.
Choosing Indentity and Access Management solution
Discover the potential of Flutter UI testing and the enhancements brought by Patrol 2.0. Find out how our dev team achieved a remarkable 10x improvement in the efficiency and reliability o UI tests, unleashing streamlined testing workflows. Dive into the article and improve your Flutter UI testing process.
Patrol UI Testing Framework by LeanCode
Most digital products fail to address the rising needs of users with impairments. One of the reasons why business owners don’t decide to implement accessibility standards is a concern that it may raise the cost of web development. Read how to improve web and web app accessibility at a low cost.
accessibility in web design