·15 min read·By

A Practical Guide to OAuth2, OIDC & SAML

OAuth2, OIDC, and SAML in plain English — what each one actually solves, when to reach for which, how they fit together in Keycloak, and the IAM habits that keep you off 2 AM incident calls.

oauth2oidcsamlkeycloakiamsecurityssobackend
A Practical Guide to OAuth2, OIDC & SAML

Picture this: you're building an app, and you want users to sign in with Google. Or maybe you're working at a company where employees need to access 15 different internal tools without entering their password 15 times. Or perhaps you're integrating with a partner company's system and need to securely share user identities.

If any of these scenarios sound familiar, you've probably bumped into OAuth2, OpenID Connect (OIDC), or SAML — the three protocols that quietly power most of the authentication and authorization we experience online every single day.

I've spent countless hours wrestling with these protocols, debugging token issues at 2 AM, and architecting IAM solutions that make developers' lives easier. Through all of that, I've learned that while these protocols might seem intimidating at first, they're actually quite elegant once you understand what problem each one solves.

Let me share what I've learned about these three protocols, why they matter, and how they work together in the real world — especially when you're working with platforms like Keycloak that bring them all together under one roof.

Table of Contents

  • OAuth2: The Authorization Framework
  • OpenID Connect (OIDC): Authentication on Top of OAuth2
  • SAML: The Enterprise Standard
  • Key Differences and When to Use Each
  • Real-World Implementation with Keycloak
  • Best Practices for Enterprise IAM

OAuth2: The "Can I Do This?" Protocol

But, What is OAuth2, Really 🤔?

Here's the thing about OAuth2: it's not about who you are — it's about what you're allowed to do. Think of it like a valet key for your car. You give someone a valet key that lets them park your car, but they can't open the glove box or trunk. That's OAuth2 in a nutshell: authorization without full access.

💡 Note: OAuth2 (Open Authorization 2.0) is an authorization framework — notice I said "authorization," not "authentication." This is a crucial distinction that trips up a lot of people. OAuth2 answers the question: "Can this app access my data?" It doesn't answer: "Who is this user?"

The Cast of Characters

Let me introduce you to the key players in any OAuth2 flow with a personal touch:

  • Resource Owner: the person who owns the data (your photos, your emails, your cat memes).
  • Client: the app that wants access (maybe a photo printing service that wants your Instagram photos).
  • Authorization Server: the bouncer at the club — it checks IDs and hands out wristbands (tokens).
  • Resource Server: the actual API holding your stuff (like the Google Drive API or GitHub API).

The OAuth2 Dance (Authorization Code Flow)

  1. Your app says: "Hey user, want to connect your Google account?"
  2. User clicks "Yes" and gets whisked away to Google's login page.
  3. User logs in and says: "Yes, let this app access my photos."
  4. Google sends them back with a special code (not the actual access yet!).
  5. Your app exchanges that code for an access token (behind the scenes).
  6. Now your app can use that token to access the user's photos.

The beautiful part? The user never gives the app their password. They just grant permission, and Google handles the rest.

Real-World Scenarios Where OAuth2 Shines

  • That photo app you use: when it asks to access your Google Photos, that's OAuth2.
  • Social media schedulers: when Buffer wants to post to your Twitter, OAuth2 makes it happen.
  • Microservices talking to each other: when Service A needs to call Service B's API, OAuth2 client credentials grant makes it secure.

The Different Flavors of OAuth2 (Grant Types)

OAuth2 comes in several "grant types" — think of them as different ways to get that access token:

  1. Authorization Code: the gold standard. Most secure, perfect for web apps. This is what you'll use 90% of the time.
  2. Client Credentials: when machines talk to machines. No user involved — just service-to-service auth.
  3. Implicit: the old way. Deprecated now (thankfully), replaced by OIDC.
  4. Resource Owner Password Credentials: the "just trust me, bro" approach. Don't use this in production. Seriously.
  5. Device Code: for smart TVs and printers — devices that can't easily show a login page.

OpenID Connect (OIDC): The "Who Are You?" Protocol

OIDC: OAuth2's Identity-Savvy Sibling

Remember how I said OAuth2 doesn't tell you who the user is? Well, that's where OIDC (OpenID Connect) comes in. It's like OAuth2, but with a name tag. OIDC is essentially OAuth2 with an identity layer on top. While OAuth2 asks "Can this app access my data?", OIDC also answers "Who is this user?" It's the protocol behind those "Sign in with Google" buttons you see everywhere.

The Magic of the ID Token

Here's where OIDC gets interesting. When you use OIDC, you get back something special: an ID Token. This is a JWT (JSON Web Token) that contains actual information about the user — their email, name, maybe a profile picture URL.

Think of it like this:

  • OAuth2 access token: "Here's a key to access the API" (but doesn't tell you who you are).
  • OIDC ID token: "Here's proof that you're john@example.com, and here's your name: John Doe."

The ID token is signed (and optionally encrypted), so you can trust it. It's like a driver's license for your app.

Sometimes the ID token isn't enough. Maybe you need the user's phone number or their department. That's where the UserInfo endpoint comes in — you call it with your access token, and it gives you additional user attributes. It's like asking for more details after seeing the ID.

How OIDC Works (The Full Story)

  1. Your app: "Hey, I want to know who this user is" (includes 'openid' scope).
  2. User logs in at the identity provider (Google, Auth0, Keycloak, etc.).
  3. Identity provider says: "Here's an authorization code AND an ID token"
    • The code: for getting an access token (OAuth2 stuff).
    • The ID token: proof of who the user is (OIDC magic).
  4. Your app exchanges the code for an access token.
  5. Now you have:
    • ID Token: know who the user is.
    • Access Token: can access their resources.

Why OIDC is a Game Changer

  • No more password management: users don't need another password for your app.
  • Security: built on OAuth2's proven foundation.
  • Standardized: works the same way whether you're using Google, Microsoft, or your own Keycloak server.
  • Modern: designed for REST APIs, mobile apps, and SPAs.

Where You've Probably Seen OIDC

  • "Sign in with Google": classic OIDC in action.
  • Corporate SSO: log in once, access all your company tools.
  • Mobile apps: that seamless login experience? OIDC.
  • Modern web apps: Single Page Applications (SPAs) love OIDC.
💡 The best part: OIDC feels invisible to users. They just click a button, maybe enter their password once, and boom — they're logged in everywhere.

SAML: The Enterprise Standard

SAML: The Grandfather Everyone Still Calls 🎩

Here's the thing about SAML: if OAuth2 is the modern kid on the block and OIDC is its slightly nerdier sibling, SAML is the formal, well-dressed grandfather who's been doing this since 2005 and, weirdly, still holds most of the enterprise money.

I learned this the hard way early on. When a Fortune 500 client says "we need SSO," 8 times out of 10 they mean SAML. Not because it's technically better — but because their identity provider (Okta, ADFS, Ping) already speaks SAML fluently, and their compliance team signed off on it years ago. Modern isn't always the winning bet in the enterprise; familiar is.

The Cast (SAML edition)

  • Identity Provider (IdP): the source of truth for who a user is — Okta, ADFS, Azure AD.
  • Service Provider (SP): the app the user is trying to log into — Salesforce, Workday, your internal tool.
  • User Agent: you. Or more precisely, your browser.
  • SAML Assertion: a signed XML blob that basically says "yes, this really is John from Acme Corp, here's his email, department, and access level." Think of it as a notarized letter from the IdP.

The SAML Dance (SP-initiated Flow)

  1. You try to open internal-tool.acme.com.
  2. The SP goes, "Who's this? I don't know them," and redirects you to the IdP.
  3. IdP asks you to log in (or notices you already have a session).
  4. IdP signs a big XML assertion — that notarized letter — and hands it to your browser.
  5. Your browser POSTs it back to the SP.
  6. SP verifies the signature, reads the assertion, and lets you in.

The whole thing happens in your browser via HTTP POST redirects. No token exchange, no back-channel calls, no JWTs. Just XML. Lots and lots of XML.

Why SAML Still Wins in the Enterprise

  • Compliance loves it: SOC 2, HIPAA, and internal security teams already know how to audit SAML. Familiar means safer to them.
  • Attribute-rich: assertions can carry deep user context — department, cost center, badge number, manager email. Perfect for role-based access.
  • Vendor coverage: every serious SaaS (Salesforce, Slack, Zoom, Workday, Atlassian) has a "SAML SSO" tickbox waiting for you.
  • Battle-tested: 20 years of enterprise deployments will do that.

Where SAML Falls Short

  • XML is a nightmare compared to JSON. If you've ever debugged a SAML assertion at 2 AM, you know exactly what I mean.
  • Mobile and SPAs: SAML was designed for the server-rendered web. Native apps and JavaScript-heavy frontends don't love it.
  • No delegated authorization: SAML tells you who someone is, but wasn't designed to say "give this app scoped access to that API." That's why enterprises still bolt OIDC/OAuth2 on top for API access.
💡 Rule of thumb: if the app is a browser-based enterprise SaaS with a login page and a compliance officer breathing down its neck, SAML is probably the right call. Everywhere else, reach for OIDC.

Key Differences and When to Use Each

The Cheat Sheet I Wish I Had on Day One

Let me save you the six months I spent figuring this out.

OAuth2 OIDC SAML
What it answers "Can this app do X?" "Can this app do X, and who is the user?" "Who is the user?"
Main purpose Authorization Authentication + Authorization Authentication (SSO)
Data format JSON JSON + JWTs XML
Token you get Access token Access token + ID token Signed XML assertion
Best for APIs, delegated access Modern web / mobile login Enterprise browser SSO
Age 2012 2014 2005
Complexity Medium Medium High

Rules of Thumb I Actually Use

  • Building a "Sign in with Google/GitHub/Microsoft" flow? → OIDC.
  • Machine-to-machine API calls (backend talking to backend)? → OAuth2 client credentials.
  • Mobile app talking to your backend? → OIDC with PKCE.
  • Fortune 500 client requires SSO for their employees? → SAML (they'll ask for the metadata XML by name).
  • Building an internal portal that fronts a dozen legacy apps? → SAML for the legacy stuff, OIDC for anything new.

The Combination Nobody Warns You About

Here's the plot twist: in real enterprise deployments, you rarely pick one. You pick all three. Your CRM logs users in via SAML, your internal APIs use OAuth2 client credentials for service-to-service calls, and your shiny new customer portal uses OIDC.

Keycloak (which we'll get to next) exists in large part because someone has to sit in the middle and speak all three fluently — without losing their mind.


Real-World Implementation with Keycloak

Keycloak: The Swiss Army Knife I Keep Coming Back To

If you've made it this far, you've probably noticed I keep mentioning Keycloak. That's because I've built more IAM setups on Keycloak than any other tool, and I want to save you some of the pain I went through learning it.

Keycloak in one sentence: an open-source identity server from Red Hat that speaks OAuth2, OIDC, and SAML — with a UI to configure it all and a decent admin API on top. It's the Swiss Army knife of enterprise auth.

The Mental Model That Finally Made It Click

For a long time Keycloak felt like a maze to me. Every screen had 40 tabs, every tab had 40 fields. What finally made it click was this hierarchy:

  • Realm: a completely isolated identity universe. Think of it like an AWS account — separate users, roles, clients, everything. Most companies run one realm per environment (dev, prod) or one per tenant.
  • Client: any app or service that talks to the realm. Your React frontend, your Spring backend, and your legacy SAML SaaS are all just "clients" with different protocol settings.
  • User: a person or service account that can log in.
  • Role / Group: how you grant permissions. Roles are flat, groups are hierarchical. Use groups for org structure, roles for permissions.
  • Identity Provider: an external IdP that Keycloak federates with — "log in with your Google Workspace account, then Keycloak issues its own tokens."

Once you internalize realm → client → user → role, 80% of the admin UI stops being confusing. Promise.

A Setup I've Repeated a Dozen Times

Here's the exact recipe I use for a typical B2B SaaS setup:

  1. Create a realm per environment. Name it after the environment, not the company (e.g., acme-prod).
  2. Create clients for each app:
    • Frontend (SPA): public client, PKCE required, standard flow enabled.
    • Backend service: confidential client, client credentials grant enabled.
    • Legacy SaaS integration: SAML client with signing certs uploaded.
  3. Federate identity providers: hook up Google Workspace for internal staff, Azure AD for enterprise customers who insist on it.
  4. Design roles carefully: I create roles like orders.read, orders.write, admin — never role names like manager that map to human titles. Titles change; permissions don't.
  5. Custom claims via mappers: put tenant_id, roles, and email_verified into the token so your backend can authorize without extra DB calls.
  6. Turn on audit logging. You will need it. Not if — when.
💡 Pro tip that saved me weeks: always version your Keycloak config as JSON (via kc.sh export) and check it into git. Manual clicks in an admin UI are the enemy of reproducible environments.

Things That Bit Me (So You Don't Have To)

  • Token lifetimes matter: default access tokens are 5 minutes. That felt short until I had to explain to product why users were being logged out mid-checkout. 15 minutes with a refresh token is usually the sweet spot.
  • Realm keys are load-bearing: rotate them, but do it during a maintenance window and give consumers time to fetch the new JWKS. I forgot this once. Never again.
  • Client scopes are your friend: default scopes attach to every token; optional scopes are opt-in. Use optional scopes to avoid bloating every token with claims most APIs don't care about.
  • Don't use Keycloak as your source of truth for user profile data. Use it for identity + roles; keep rich profile data in your own DB where it belongs.

Best Practices for Enterprise IAM

The Fundamentals That Keep You Off 2 AM Incident Calls

Everything above is worth nothing if you skip the fundamentals. Here's the short list I run through on every IAM design review — internal or with a client.

Auth Flow Choices

  • Always use PKCE, even for confidential clients. Cheap insurance against auth-code interception.
  • Never use Resource Owner Password Credentials (ROPC). If a vendor asks for it, push back hard. It defeats the whole point of OAuth2.
  • Refresh token rotation on every use. The old refresh token gets invalidated the moment a new one is issued — that's how you detect and shut down token theft.

Token Hygiene

  • Short access tokens (5–15 min), longer refresh tokens (hours to days depending on risk). Don't ship access tokens with 24-hour lifetimes "because it's easier."
  • Validate tokens on every request — signature, expiry, issuer, audience. Don't trust a JWT just because it decoded.
  • Never store tokens in localStorage for browser apps. Use httpOnly, Secure, SameSite cookies, or the BFF pattern.

Scopes and Permissions

  • Least privilege by default. If an integration only needs to read invoices, don't give it invoices.*.
  • Design scopes around resources and verbs (orders.read, orders.write), not around human roles.
  • Enforce authorization at the API layer, not just the frontend. The frontend is for UX; the backend is for security.

Operational Muscle

  • Enforce MFA for admin roles and privileged accounts, always. For everyone else, at least make it an option.
  • Audit logging is not optional. Log every token issuance, revocation, admin change, and failed login. Ship it to a SIEM you actually look at.
  • Rotate signing keys on a schedule. Automate JWKS-fetching in your clients so a rotation doesn't cause an outage.
  • Have a break-glass account. One local, non-federated admin account with MFA and a rotated password in a vault. When your IdP goes down and you can't log in to fix it — and it will — you'll thank yourself.

The Human Stuff

  • Document your realm/client/scope setup so the person who inherits it doesn't have to reverse-engineer your clicks.
  • Test the recovery path. Deleted user, revoked token, IdP outage — walk through each scenario before it happens for real.
  • Talk to security early. The best IAM designs come out of a whiteboard session with your security team, not from copying an Auth0 tutorial the night before launch.
💡 Nothing in IAM is set-and-forget. The protocols are stable; the threats and your business rules aren't. Revisit your setup every six months, and treat it like production code — reviewed, tested, version-controlled.

Wrapping Up

OAuth2, OIDC, and SAML aren't competitors — they're teammates. Each one solves a different piece of the same puzzle. OAuth2 handles delegated authorization, OIDC layers identity on top of it, and SAML keeps the enterprise browser-SSO world humming along.

Pick the right one for the job, use Keycloak (or any other proper IAM platform) to stop reinventing the wheel, and follow the fundamentals — short tokens, PKCE, MFA, audit logs — and you'll end up with an auth stack that doesn't wake you up at 2 AM.

And if it does wake you up at 2 AM, at least now you'll know which of these three to blame first.