Skip to content

How IAM Compares

Different tools solve different problems well. This page is deliberately honest about where each one — including this one — wins.

IAM (this project) Keycloak OpenFGA / SpiceDB Spring Security method security
What it is embedded authZ + authN library standalone identity server (IdP) relationship-based authZ service authorization primitives in-framework
Deployment in-process, no extra service separate server (+ DB) to run, patch, scale separate service (+ store); network hop per check in-process
Decision latency in-memory after cached resolution network hop (token introspection/UMA) network hop per check (batching helps) in-memory
Model RBAC + scopes + field-level, DENY-wins realms, roles, groups; authZ services (UMA) ReBAC — relationship tuples, Zanzibar-style whatever you encode in SpEL/annotations
Field-level responses built-in (@FieldFiltered) no no (object/relationship granularity) DIY
Admin plane REST API + React admin UI included full admin console API (+ playground); UI is yours to build none — you build it
Explain/why decision trace API built-in limited check/expand APIs help debugging none
Users/login built-in or SPI to your user table full IdP: SAML, OIDC, federation, brokering none — bring your own authN none — pair with something
Ops burden your app’s burden only one more stateful service one more stateful service none

Keycloak is a server-based identity provider — a separate product you deploy, upgrade, theme, and operate. It shines when you need to be an IdP: SSO across many applications, SAML, identity brokering, social login at the organizational level, offloading login UI entirely.

IAM is a library inside your app. There is no second service to run; permission checks are in-process; field-level filtering and the DENY-wins three-tier model are first-class, which Keycloak’s role model doesn’t attempt. The trade: IAM is not a federation hub. If “our customers demand SAML with their corporate IdP today” describes you, Keycloak (or a managed IdP) is the right call — some teams run both, with the IdP authenticating and an embedded layer authorizing.

The Zanzibar family models authorization as a graph of relationship tuples — spectacular for Google-Drive-shaped problems: deep sharing hierarchies, “viewer of the parent folder”, billions of objects, cross-service consistency.

The costs: it’s another stateful service, every check is a network call, you must keep the tuple store in sync with your database (a hard distributed-systems problem), and there’s no concept of response field filtering — that stays your job. If your model is “roles, groups, scopes, and some sensitive fields” — which is most B2B applications — a ReBAC engine is paying Google-scale complexity for capabilities you won’t use. If your model genuinely is a sharing graph, IAM’s role/scope model will fight you; use the right tool.

@PreAuthorize("hasRole('MANAGER')") is free and in-process — and it’s where most projects start. What it doesn’t give you grows over time: permissions live in code, so changing who can approve means a deployment, not an admin click. There’s no admin UI, no group/role hierarchy resolution, no field-level rules, no audit trail, no “why was this denied”, no cache with invalidation. Each is a week of DIY; together they’re this project.

Notably, IAM builds on Spring Security rather than replacing it: the filter chain, method security, and SecurityContext all remain — you can even bring your own chain.

Honesty is the feature:

  • You need SAML or enterprise federation today. IAM speaks JWT and OAuth2/OIDC login, not SAML, and it is not an identity broker. Use Keycloak or a managed IdP (possibly in front of IAM).
  • You need Google-scale ReBAC. Deep sharing graphs and relationship inheritance across billions of objects are Zanzibar’s home turf, not a role/scope model’s.
  • You’re not on Spring Boot. IAM is a Spring Boot library by design — that’s what “embedded” buys. Other stacks need a service-shaped authorizer.
  • You want authorization decisions shared by many polyglot services. In-process means per-service. (JWT verification across services works via JWKS, but the policy engine itself lives in the Spring app.)
  • A one-page app with two roles. Spring Security’s built-ins are fine. Come back when someone asks for an admin screen or field-level rules.