Skip to main content
Resources Security 9 min read

Keycloak vs Auth0 vs Cognito: Self-Hosted vs Managed Identity

Keycloak gives you full control. Auth0 gives you developer experience. Cognito gives you AWS integration. Here's how to pick your identity provider.

Picking an identity provider feels like it should be straightforward. You need login, signup, maybe social connections and MFA. Three platforms come up in every conversation: Keycloak, Auth0, and Amazon Cognito. They all handle authentication. They all support OAuth 2.0 and OIDC. But the similarities end there, because each one reflects a fundamentally different philosophy about who should own identity infrastructure and how much you should pay for it.

The wrong choice here is expensive to reverse. Identity touches every service, every user flow, every compliance audit. Migrating off an IdP mid-growth is the kind of project that derails roadmaps for quarters.

Three Models of Identity

Keycloak is a self-hosted, open-source identity and access management server. You run it on your infrastructure, you own the data, you handle the ops. Red Hat backs the project, and it ships as a CNCF-adjacent Java application built on Quarkus.

Auth0 is a developer-focused identity SaaS (now owned by Okta). You integrate their SDKs, configure through their dashboard or Management API, and they handle the infrastructure. You pay per monthly active user.

Amazon Cognito is AWS’s managed identity service. It’s deeply wired into the AWS ecosystem–API Gateway, ALB, AppSync, Lambda–and priced aggressively on a per-MAU basis. It trades customization for tight cloud-native integration.

These aren’t interchangeable products with different logos. They represent distinct trade-offs between control, developer experience, cost structure, and operational burden.

Keycloak: Full Control, Full Responsibility

Keycloak is the most feature-complete open-source identity server available. It supports OIDC, SAML 2.0, and LDAP/Active Directory federation out of the box. The admin console is genuinely powerful–realm-based multi-tenancy, fine-grained authorization, user federation, identity brokering, and a theming system that lets you fully customize login flows.

Where Keycloak excels:

  • Protocol support. OIDC, SAML, LDAP, Kerberos. If an enterprise partner hands you a SAML metadata file, Keycloak handles it natively. No workarounds, no feature gates.
  • Multi-tenancy. Realms provide hard isolation between tenants. Each realm gets its own users, clients, roles, themes, and identity providers. This is real multi-tenancy, not namespace hacks.
  • Customization depth. Custom authentication flows, custom user storage providers (SPIs), event listeners, protocol mappers. You can override almost anything without forking the project.
  • Data sovereignty. Your users, your database, your infrastructure. No third party ever sees your identity data. For regulated industries or government contracts, this can be a hard requirement.

Where Keycloak hurts:

  • Operational overhead. You’re running a stateful Java application that needs a database (PostgreSQL, typically), clustering for HA, certificate management, upgrades, and monitoring. This isn’t a sidecar you deploy and forget.
  • Upgrade pain. Major version upgrades (especially the move from WildFly to Quarkus-based Keycloak) have historically required migration effort. Database schema changes, theme compatibility breaks, SPI API changes.
  • No managed option. There’s no hosted Keycloak. Red Hat offers Red Hat build of Keycloak with support, and third parties like Phase Two offer hosting, but you’re still closer to the metal than with Auth0 or Cognito.
  • Developer experience. The documentation is adequate but inconsistent. SDK support is limited compared to Auth0. You’ll spend more time reading source code and Stack Overflow than you’d like.

Keycloak is the right choice when you need full protocol support, data sovereignty, deep customization, or you’re operating at a scale where per-MAU pricing becomes absurd. It’s the wrong choice if your team doesn’t have the bandwidth to operate stateful infrastructure.

Auth0: Developer Experience as a Product

Auth0 understood something early: developers choose identity providers, and developers care about how fast they can integrate. The result is an IdP where the getting-started experience is genuinely excellent. Drop in Universal Login, configure a connection, and you have working authentication in under an hour.

Where Auth0 excels:

  • SDK ecosystem. First-class SDKs for React, Next.js, Angular, Vue, Express, Django, Rails, Spring Boot, Flutter, React Native–basically every framework that matters. These aren’t thin wrappers; they handle token management, session refresh, and edge cases.
  • Universal Login. A hosted, customizable login page that handles MFA, social connections, password reset, and progressive profiling. Centralizing login on Auth0’s domain simplifies security (no token leakage through redirect bugs) and provides a consistent experience.
  • Actions and Rules. Extensibility through JavaScript functions that run during authentication flows. Need to enrich tokens with data from your API? Block login from certain countries? Sync user data to your CRM on signup? Write an Action.
  • Organizations. Auth0’s Organizations feature is purpose-built for B2B SaaS. Each organization gets its own connections, branding, MFA policies, and member management. If you’re building multi-tenant B2B software, this feature alone can save months of development.
  • Social connections. Google, GitHub, Apple, Microsoft, LinkedIn–pre-built and maintained. Auth0 handles the OAuth dance with each provider, token refresh, and profile normalization.

Where Auth0 hurts:

  • Price. Auth0’s free tier is generous for prototyping (7,500 MAU), but costs escalate quickly. The B2B plan with Organizations starts at $150/month for 500 MAU and climbs steeply. At 100,000 MAU, you’re looking at enterprise pricing that can easily hit five figures monthly.
  • Vendor lock-in. Auth0’s Actions, Rules, and Hooks are proprietary. Your extensibility code doesn’t port to another IdP. Universal Login customization uses Auth0-specific templating. Migration away from Auth0 means rewriting integration code across every service.
  • Rate limits and quotas. Management API rate limits (varying by plan tier) can bite you during bulk operations, migrations, or automated user provisioning. The Authentication API has its own limits that matter at scale.
  • Okta acquisition uncertainty. Since the Okta acquisition, some features have been repositioned, pricing has shifted, and the long-term product direction is less clear than it was under independent Auth0.

Auth0 is the right choice when developer velocity matters most, when you’re building B2B SaaS with the Organizations feature, or when your team is small and can’t justify hiring identity infrastructure specialists. It’s the wrong choice when per-MAU costs at your scale make the math untenable.

Cognito: The AWS Tax on Identity

Cognito is two services stitched together: User Pools (authentication–signup, login, MFA, token issuance) and Identity Pools (authorization–mapping authenticated users to IAM roles for AWS resource access). The integration between them is powerful if you’re all-in on AWS, and confusing if you’re not.

Where Cognito excels:

  • AWS integration. Cognito plugs directly into API Gateway (authorizer), ALB (authentication action), AppSync (authorization), and Lambda (triggers). If your architecture is API Gateway + Lambda, Cognito authentication is essentially zero-code.
  • Price. The first 50,000 MAU are free. Beyond that, pricing drops to fractions of a cent per MAU. At 1 million MAU, Cognito costs roughly $4,550/month. Auth0 at that scale would be an order of magnitude more. For consumer apps with large user bases, this pricing difference is decisive.
  • Lambda triggers. Pre-signup, pre-authentication, post-authentication, pre-token-generation, custom message, custom email sender. Lambda triggers give you extensibility at every step of the authentication flow, using any Lambda-supported runtime.
  • Identity pools for AWS access. Need authenticated users to upload to S3, query DynamoDB, or invoke other AWS services directly? Identity Pools map Cognito (or federated) identities to IAM roles. This is a capability that Auth0 and Keycloak simply don’t have natively.

Where Cognito hurts:

  • Customization ceiling. The hosted UI is notoriously limited. Theming options are minimal–you get a logo, a background color, and CSS overrides that fight the default styles. Most teams end up building custom login UIs, which eliminates one of the main benefits of a managed service.
  • Developer experience. The AWS SDK for Cognito is verbose, the documentation mixes User Pools and Identity Pools concepts confusingly, and error messages are cryptic. Simple operations like “change a user’s email” require understanding of attribute verification flows that aren’t intuitive.
  • Missing features. No built-in Organizations or multi-tenancy concept. No equivalent to Auth0 Actions for post-login logic beyond Lambda triggers. No pre-built social connection management UI–you configure OIDC providers manually through the console or CloudFormation. Breached password detection is limited compared to Auth0.
  • Migration difficulty. You cannot export user passwords from Cognito. If you migrate away, every user must reset their password. This is also true of Auth0 for hashed passwords, but Cognito’s migration Lambda trigger for gradual migration into Cognito doesn’t have an equivalent for migrating out.
  • Operational surprises. Cognito has hard limits that can’t always be raised–like the 40 custom attributes per user pool limit, or the maximum number of groups. These limits feel arbitrary until you hit them in production.

Cognito is the right choice when you’re building on AWS, your user base is large (making per-MAU cost the dominant factor), and your authentication requirements are standard. It’s the wrong choice when you need deep customization, a polished hosted login experience, or B2B multi-tenancy.

Developer Experience: Auth0 Wins, and It’s Not Close

Integrating Auth0 into a new Next.js application takes about 20 minutes. Install @auth0/nextjs-auth0, add three environment variables, wrap your app in UserProvider, and you have working authentication with Universal Login, session management, and API route protection.

Integrating Cognito into the same application takes hours. You’re configuring Amplify (or the raw AWS SDK), dealing with User Pool and App Client settings, understanding the difference between the hosted UI and custom UI flows, and debugging cryptic error responses. The Amplify library abstracts some complexity but introduces its own opinions about project structure.

Integrating Keycloak takes longer still if you’re starting from scratch. You need to deploy Keycloak itself (Docker, Kubernetes, or bare metal), create a realm, configure a client, then integrate using a community-maintained adapter or a generic OIDC library. The payoff is more control, but the time-to-first-login is measured in days, not minutes.

Documentation quality follows the same ranking. Auth0’s docs include framework-specific quickstarts that actually work, interactive API explorers, and architecture guidance. Cognito’s docs are comprehensive but written for an audience that already understands AWS’s IAM model. Keycloak’s docs cover features thoroughly but lack the guided, tutorial-style approach that gets teams productive quickly.

Cost at Scale

This is where the comparison gets interesting, because the cheapest option depends entirely on your scale and what you count as cost.

Keycloak: Infrastructure only. A production Keycloak cluster on AWS (two application nodes, managed PostgreSQL, load balancer) runs roughly $300-600/month. That price doesn’t change whether you have 1,000 or 1,000,000 users. Your real cost is engineering time–operating, upgrading, and debugging Keycloak is an ongoing commitment.

Auth0: Per-MAU pricing. The free tier covers 7,500 MAU. The Essentials plan starts at $35/month. But B2B features (Organizations, enterprise connections) require the Professional plan ($240/month base) or Enterprise. At 100,000+ MAU with enterprise features, expect $3,000-15,000+/month depending on your contract.

Cognito: Per-MAU pricing, but cheaper. Free tier covers 50,000 MAU. Beyond that, pricing tiers range from $0.0055/MAU (50K-100K) down to $0.0025/MAU (10M+). Advanced security features (adaptive authentication, compromised credential detection) add $0.050/MAU, which changes the math significantly.

The crossover point: Keycloak becomes cheaper than Auth0 around 10,000-20,000 MAU, depending on your Auth0 plan and Keycloak infrastructure costs. Cognito is cheaper than Auth0 at almost any scale if you don’t need Auth0-specific features. But Cognito’s hidden cost is the engineering time spent working around its limitations–building custom UIs, implementing multi-tenancy, and handling edge cases that Auth0 solves out of the box.

Customization and Extensibility

All three platforms are extensible, but the mechanisms and limits differ dramatically.

Keycloak gives you the deepest hooks. Service Provider Interfaces (SPIs) let you replace or extend authentication flows, user storage, event handling, token generation, and protocol mapping. You can write a custom authenticator that integrates your legacy database, or a user federation provider that syncs with an obscure HR system. The trade-off: SPIs are Java-based, require deployment alongside Keycloak, and can break on upgrades.

Auth0 provides extensibility through Actions–serverless JavaScript/TypeScript functions triggered at specific points in the authentication pipeline (post-login, pre-registration, post-change-password). Actions run in Auth0’s sandboxed Node.js environment with npm package support. They’re easier to write and deploy than Keycloak SPIs, but more constrained. You can’t replace the core authentication engine or fundamentally alter how Auth0 works.

Cognito offers Lambda triggers at various lifecycle points. These are more powerful than Auth0 Actions in one sense (any Lambda runtime, any AWS service access) but more limited in another (fewer trigger points, no equivalent to Auth0’s post-login Action for token enrichment without the pre-token-generation trigger’s constraints).

Login UI Customization

This matters more than most teams expect. Your login page is the first thing users see.

Auth0’s Universal Login supports extensive customization through the New Universal Login experience (Lock-based) or Classic Universal Login (fully custom HTML/CSS/JS). The new Auth0-hosted pages are responsive, accessible, and handle edge cases like password managers and autofill.

Keycloak’s theming system lets you override FreeMarker templates and CSS for every login page variant (login, registration, password reset, OTP, etc.). It’s powerful but requires understanding Keycloak’s template structure. The default theme is functional but dated.

Cognito’s hosted UI is the weakest of the three. Limited CSS customization, no template overrides, no conditional rendering. Most serious Cognito deployments abandon the hosted UI entirely and build custom login pages using the Cognito SDK, which is more work than it sounds.

When to Choose Each

Choose Keycloak when:

  • Data sovereignty is non-negotiable (government, healthcare, financial services with strict compliance)
  • You need SAML support for enterprise federation alongside OIDC
  • Your user count makes per-MAU pricing unreasonable (500K+ users)
  • You need deep protocol-level customization that managed services can’t provide
  • Your team has the infrastructure expertise to run and maintain it
  • You’re building on-premises software that can’t depend on external SaaS

Choose Auth0 when:

  • Developer velocity is the priority and your team is small
  • You’re building B2B SaaS and need the Organizations feature
  • You need excellent social login support with minimal configuration
  • Your MAU count is moderate (under 50,000) and the pricing works
  • You want best-in-class documentation and SDK support
  • Time-to-market matters more than long-term per-user cost

Choose Cognito when:

  • Your architecture is deeply AWS-native (API Gateway, Lambda, AppSync)
  • You have a large consumer user base where per-MAU cost dominates
  • Your authentication requirements are standard (email/password, social login, MFA)
  • You need Identity Pools for direct AWS resource access from client applications
  • You’re comfortable building custom login UIs
  • The 50,000 free MAU tier covers your needs for the foreseeable future

The Bottom Line

There’s no universally correct answer here, but there are clearly wrong ones. Running Keycloak with a two-person team that doesn’t want to manage infrastructure is wrong. Paying Auth0 enterprise pricing for a consumer app with 2 million MAU is wrong. Choosing Cognito for a B2B platform that needs per-organization branding and enterprise SSO connections is wrong.

If you’re a startup building B2B SaaS with a small team, start with Auth0. The developer experience and Organizations feature will save you months. Accept the per-MAU cost as the price of moving fast, and revisit the decision if pricing becomes painful at scale.

If you’re an AWS shop building consumer-facing applications, Cognito’s pricing and native integration make it the default choice. Budget engineering time for building custom login UIs and working around its rough edges.

If you need full control–because of compliance, scale, protocol requirements, or principle–Keycloak is the only serious open-source option. Invest in the operational capability to run it well, or the cost savings over managed alternatives will be consumed by engineering time spent fighting fires.

The identity provider decision is ultimately about what kind of problem you’d rather have: operational complexity (Keycloak), vendor lock-in and cost scaling (Auth0), or limited customization within a walled garden (Cognito). Pick the problem that best matches your team’s strengths and your product’s constraints.

Have a Project
In Mind?

Let's discuss how we can help you build reliable, scalable systems.